• Regolamento Macrocategoria DEV
    Prima di aprire un topic nella Macrocategoria DEV, è bene leggerne il suo regolamento. Sei un'azienda o un hosting/provider? Qui sono anche contenute informazioni per collaborare con Sciax2 ed ottenere l'accredito nella nostra community!

Guida Gestione Della Memoria in C


E perché non commenti la frase

calling free twice ("double free"), etc., usually causes a segmentation fault and results in a crash of the program

parola per parola ... cosa significa secondo te?

questa invece son curioso

Parlo di DevCpp e del suo compilatore che nella versione 4.9.9.2 è bacatissimo. Putroppo viene usato ancora in molte facoltà ma se solo partecipassi a forum più specifici, dove ci sono professionisti che scrivono, ne sapresti qualcosa in più. Per CB nulla da dire, nella versione aggiornata con GCC. @System32

(dato che MSVC usa uno standard vecchio ...)

MSVC (2013 e adesso il 2014 che sto provando in preview) non mi pare sia vecchio ... informati.
 
Parlo di DevCpp e del suo compilatore che nella versione 4.9.9.2 è bacatissimo. Putroppo viene usato ancora in molte facoltà ma se solo partecipassi a forum più specifici, dove ci sono professionisti che scrivono, ne sapresti qualcosa in più. Per CB nulla da dire, nella versione aggiornata con GCC. @System32
DevCpp della Bloodshed è rimasto alla 4.9.9.2, ma quello portato avanti dalla Orwell ha aggiornato il compilatore all'ultima versione.

Comunque una domanda, fare un free su un puntatore nullo, non equivale a fare un free su una variabile come può esserlo int?

ps. Personalmente a me piace quando si dibatte su un forum su un qualcosa su cui non tutti sono d'accordo, perché può portare ad una soluzione per tutti
 
DevCpp della Bloodshed è rimasto alla 4.9.9.2, ma quello portato avanti dalla Orwell ha aggiornato il compilatore all'ultima versione.

Corretto, purtroppo moltissimi usano ancora il primo.

Comunque una domanda, fare un free su un puntatore nullo

Le specifiche della funzione free (le trovi ovunque) indicano che se si usa un puntatore nullo non succede nulla (la free termina senza operare nè con errori).

Il resto della domanda (sulla variabile int) non l'ho capita ...

ps. Personalmente a me piace quando si dibatte su un forum su un qualcosa su cui non tutti sono d'accordo, perché può portare ad una soluzione per tutti

Esatto
 
@Rikku @nothing

Per quanto riguarda la questione di ciò che accada dopo free ,il puntatore fa riferimento a un area di memoria indefinita(Il puntatore non è nullo). Riutilizzabile e riallocabile normalmente , solo nel caso si facesse riferimento a quest'ultimo quando è deallocato porterebbe alla scrittura di altre aree di memoria in quest'area indefinita.Con un inesorabile crash , per tanto levare la locazione del puntatore da maggior sicurezza .

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

In questo modo anche si usasse il codice deallocato non porterebbe anomilie.

Per quanto riguarda la questione delle due chiamata di free , come già detto Nothing, causa un undefined behavior o almeno in teoria il compilatore dovrebbe gestirla. Per tanto l'unica soluzione accettabile è la prima elencata nella guida . Aggiorno la guida.

Comunque una domanda, fare un free su un puntatore nullo, non equivale a fare un free su una variabile come può esserlo int?
no , non è la stessa cosa. Dato che una variabile int è allocata staticamente ^^ e non puoi liberare con free
 
Ultima modifica:
Le specifiche della funzione free (le trovi ovunque) indicano che se si usa un puntatore nullo non succede nulla (la free termina senza operare nè con errori).
Il resto della domanda (sulla variabile int) non l'ho capita ...

Quindi il problema nasce se provo a fare free su un puntatore già svuotato. Cioè: se io faccio free(p);, la memoria viene liberata.
Se io faccio nuovamente free(p); ( che è quello che stiamo discutendo qua se ho capito bene xD ) Dovrebbe dare un errore perché quello spazio in memoria non esiste più per così dire, e questo porta ad un crash per segmentation fault, proprio come accade utilizzando l'ASM se si prova ad accedere ad informazioni inesistenti.

@Rikku @nothing

Per quanto riguarda la questione di ciò che accada dopo free ,il puntatore fa riferimento a un area di memoria indefinita(Il puntatore non è nullo). Riutilizzabile e riallocabile normalmente , solo nel caso si facesse riferimento a quest'ultimo quando è deallocato porterebbe alla scrittura di altre aree di memoria in quest'area indefinita.Con un inesorabile crash , per tanto levare la locazione del puntatore da maggior sicurezza .

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

In questo modo anche si usasse il codice deallocato non porterebbe anomilie.

Per quanto riguarda la questione delle due chiamata di free , come già detto Nothing, causa un undefined behavioro almeno in teoria dovrebbe causarla. Per tanto l'unica soluzione accettabile è la prima elencata nella guida . Aggiorno la guida.

no , non è la stessa cosa. Dato che una variabile int è allocata staticamente ^^ e non puoi liberare con free

Praticamente, quello che stai dicendo nella prima parte è che per l'appunto, si potrebbe rischiare di effettuare qualche operazione su quel puntatore dopo averlo "pulito" e quindi ricadere in errore, e per questo è sempre meglio porre il puntatore uguale a NULL per evitare problemi, e sono d'accordo ( sto cercando di riassumere per vedere se ho capito bene, perdonatemi please XD )

Per la seconda, so che effettuare un free su un int non si può fare, però non comprendo una cosa che magari sarà una cavolata che dico io.

Nel momento in cui io provo a fare una cosa del tipo free(&numero); non sto passando alla funzione free un puntatore ad un area di memoria in cui potrà trovare una cella di memoria contenente il valore di numero? Quindi questo non è accettabile, mentre fare free(ptr); sì, che è alla fin fine sempre un puntatore?
 
Solo qualche precisazione sulla terminologia, che sembra poco utile ma che invece è sostanziale

Per quanto riguarda la questione di ciò che accada dopo free ,il puntatore fa riferimento a un area di memoria indefinita

"Area di memoria indefinita" non è un termine corretto.

Il puntatore punta ad un'area di memoria non allocata al processo. Ovvero il processo non dispone del "set di indirizzi virtuali" prima allocati con la malloc.

E' un discorso complesso che ci porterebbe troppo in là e che prevede la conoscenza di quello che c'è dietro la "gestione della memoria per i processi".

levare la locazione del puntatore da maggior sicurezza .

"Levare la locazione del puntatore" è una terminologia non corretta.

Semplicemente si indica che il contenuto del puntatore deve essere posto uguale a NULL.
NULL è rappresentato da 0 che è un indirizzo particolare per i sistemi dato che l'indirizzo virtuale 0 non è utilizzabile dai processi. Quindi

ptr=NULL;

indica soltanto che il puntatore non punta a nessuna area di memoria valida per il processo.

In questo modo anche si usasse

Anzi, proprio perché NULL, se si usasse per sbaglio il puntatore, il programmatore si accorgerebbe subito del problema perché in questo caso non esisterebbe un "undefined behavior" ma una conseguenza obbligatoria (crash con codice 0xc0000005 violation error).

Per quanto riguarda la questione delle due chiamata di free ... causa un undefined behavior

Questa non è una condizione di errore (che viene causata). Forse non ci intendiamo con i termini.
UB significa che il comportamento del compilatore in questo caso non è definito dallo standard e che questa condizione può portare a strani comportamenti diversi da caso a caso, da NIENTE a un CRASH. E' comunque una condizione da EVITARE.

- - - Aggiornato - - -

che è quello che stiamo discutendo qua

Sì, corretto con la sola correzione che il doppio free implica che il secondo opera su un puntatore non valido. Questo fatto NON è contemplato dallo standard e quello che può succedere non è definito e non è sempre uguale per ogni compilatore (neanche per ogni esecuzione dello stesso programma). Quindi può succedere di tutto, da niente ad un crash. Ma è comunque un grave errore prevedere nel codice un doppio free dello stesso puntatore.

è sempre meglio porre il puntatore uguale a NULL per evitare problemi

Sì, perché dopo la prima free se si usasse il puntatore non più valido potresti anche creare problemi senza accorgertene. Il NULL evita questo problema perché obbliga il runtime al crash.

Nel momento in cui io provo a fare una cosa del tipo free(&numero);

Lo standard del C implica che si segua sempre lo schema malloc-free. Quindi i puntatori validi su cui può operare la free sono quelli rilasciati in precedenza dalla malloc. Quello che fornisci in quel modo non è tra quelli presenti nelle tavole di allocazione (su cui operano malloc-free) e quindi hai un "comportamento indefinito" (da niente a crash) ma sicuramente non deallochi l'int.
 
Ultima modifica:
  • Like
Reactions: 2 people
Solo qualche precisazione sulla terminologia, che sembra poco utile ma che invece è sostanziale



"Area di memoria indefinita" non è un termine corretto.

Il puntatore punta ad un'area di memoria non allocata al processo. Ovvero il processo non dispone del "set di indirizzi virtuali" prima allocati con la malloc.

E' un discorso complesso che ci porterebbe troppo in là e che prevede la conoscenza di quello che c'è dietro la "gestione della memoria per i processi".



"Levare la locazione del puntatore" è una terminologia non corretta.

Semplicemente si indica che il contenuto del puntatore deve essere posto uguale a NULL.
NULL è rappresentato da 0 che è un indirizzo particolare per i sistemi dato che l'indirizzo virtuale 0 non è utilizzabile dai processi. Quindi

ptr=NULL;

indica soltanto che il puntatore non punta a nessuna area di memoria valida per il processo.



Anzi, proprio perché NULL, se si usasse per sbaglio il puntatore, il programmatore si accorgerebbe subito del problema perché in questo caso non esisterebbe un "undefined behavior" ma una conseguenza obbligatoria (crash con codice 0xc0000005 violation error).



Questa non è una condizione di errore (che viene causata). Forse non ci intendiamo con i termini.
UB significa che il comportamento del compilatore in questo caso non è definito dallo standard e che questa condizione può portare a strani comportamenti diversi da caso a caso, da NIENTE a un CRASH. E' comunque una condizione da EVITARE.

- - - Aggiornato - - -



Sì, corretto con la sola correzione che il doppio free implica che il secondo opera su un puntatore non valido. Questo fatto NON è contemplato dallo standard e quello che può succedere non è definito e non è sempre uguale per ogni compilatore (neanche per ogni esecuzione dello stesso programma). Quindi può succedere di tutto, da niente ad un crash. Ma è comunque un grave errore prevedere nel codice un doppio free dello stesso puntatore.



Sì, perché dopo la prima free se si usasse il puntatore non più valido potresti anche creare problemi senza accorgertene. Il NULL evita questo problema perché obbliga il runtime al crash.



Lo standard del C implica che si segua sempre lo schema malloc-free. Quindi i puntatori validi su cui può operare la free sono quelli rilasciati in precedenza dalla malloc. Quello che fornisci in quel modo non è tra quelli presenti nelle tavole di allocazione (su cui operano malloc-free) e quindi hai un "comportamento indefinito" (da niente a crash) ma sicuramente non deallochi l'int.

Perfetto. Adesso ho tutto limpido in testa, ti ringrazio, sembrano sciocchezze ma è molto importante stare attenti a queste cose, che possono fare la differenza all'interno di un programma.
 
Non credo che ci fosse il bisogno di discutere ulteriormente dell'utilizzo della free due volte, bastava leggere il codice fornito da Wikipedia come spiegazione :

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

L'ultima riga chiarifica perfettamente che assegnando al puntatore ptr il valore NULL questo potrà essere riciclato, ovvero riutilizzato finché non si chiama la malloc. Io credo che prima di gestire la memoria in C bisogna avere chiaro in mente dove vengono salvate le variabili, a livello di memoria, e come gestire al meglio le funzioni che operano con la memoria. Per il resto la maggior parte di quello che avrei voluto scrivere l'ha scritta @nothing

PS :
Perfavore, Entra oppure Registrati per vedere i Link!
 
Ultima modifica: