[C] funzionamento free
Buongiorno, ipotizzando di avere una lista dove ogni nodo e':
Io ho fatto così: (con l'intenzione di liberare prima ogni singolo campo e poi il puntatore ad ogni nodo)
quando la chiamo l è il puntatore al primo nodo
ma da errore, credo perché free si aspetta un puntatore alla memoria da liberare e non un valore preciso..
Allora si fa così? Si liberano da soli tutti i campi dei nodi? Facendo così ho l'impressione di cancellare solo il puntatore ai nodi ma i nodi continuano ad esistere..
Potreste darmi qualche dritta? Grazie in anticipo!
typedef struct struttura *Ptr; struct struttura { int a; float b; Ptr successivo; }
Io ho fatto così: (con l'intenzione di liberare prima ogni singolo campo e poi il puntatore ad ogni nodo)
quando la chiamo l è il puntatore al primo nodo
void funzionelibero(link l) { if (l->successivo== NULL) { free(l->a); free(l->b); return; } funzionelibero(l->successivo); free(l); }
ma da errore, credo perché free si aspetta un puntatore alla memoria da liberare e non un valore preciso..
void funzionelibero(link l) { if (l->successivo== NULL) { return; } funzionelibero(l->successivo); free(l); }
Allora si fa così? Si liberano da soli tutti i campi dei nodi? Facendo così ho l'impressione di cancellare solo il puntatore ai nodi ma i nodi continuano ad esistere..
Potreste darmi qualche dritta? Grazie in anticipo!
Risposte
Free libera la memoria, allocata dinamicamente, che è associata a quel puntatore. Free non va mai usato su variabili che non siano puntatori o su puntatori che non siano il valore di ritorno di un malloc, realloc o calloc chiamati precedentemente. Pertanto quando chiami free su successivo rilasci tutta la memoria del nodo successivo. Devi stare attento che se sbagli l'ordine dei free ti troveresti con dei Memory leak.
Mi spiace ma credo di non aver ancora capito come fare praticamente..
Allora l'ultimo pezzo di codice che ho scritto dovrebbe essere giusto no?
"vict85":
Pertanto quando chiami free su successivo rilasci tutta la memoria del nodo successivo.
Allora l'ultimo pezzo di codice che ho scritto dovrebbe essere giusto no?
Se mi spieghi cosa stai cercando di fare e posti il codice per intero, provo ad aiutarti.
Lo farei volentieri ma l' "esercizio" era solo questo.. sono agli inizi dell'allocazione dinamica e delle liste..
Supponendo di avere una lista con i nodi strutturati in quella maniera e già allocata dinamicamente, creare una funzione per liberare la memoria..
Dovrebbe essere semplice però non so come aiutarti ad aiutarmi.. Provo a fare uno schemino della lista ma non so quanto possa servire
Supponendo di avere una lista con i nodi strutturati in quella maniera e già allocata dinamicamente, creare una funzione per liberare la memoria..
Dovrebbe essere semplice però non so come aiutarti ad aiutarmi.. Provo a fare uno schemino della lista ma non so quanto possa servire

Mi sembra che l'ultimo sia corretto, ma tendi ad abusare un po' dei typedef. Il tipo Link è lo stesso di Ptr ovvero struct struttura* ? Se è così allora dovrebbe essere corretto, se non è così allora è sbagliato (ma in quel caso non dovrebbe neanche compilarti).
"vict85":
Mi sembra che l'ultimo sia corretto, ma tendi ad abusare un po' dei typedef. Il tipo Link è lo stesso di Ptr ovvero struct struttura* ? Se è così allora dovrebbe essere corretto, se non è così allora è sbagliato (ma in quel caso non dovrebbe neanche compilarti).
Sisi link lo stesso di Ptr, in effetti dovrei usarne solo uno per miglior chiarezza..
Vi ringrazio per le vostre risposte e disponibilità, ho chiarito il dubbio e appreso anche il concetto di memory leak che ignoravo! Buona domenica a tutti
Dall'ultimo codice che hai postato si deduce che hai capito come utilizzare la funzione free, ma c'è un errore di logica nel modo in cui hai implementato la funzione funzionelibero. Infatti essa elimina tutti i nodi escluso quello di coda. Per esempio se la lista è costituita da un solo nodo (in questo caso il nodo di coda coincide con quello di testa), l->successivo sarà uguale a NULL e quindi a causa del return la memoria non verrà liberata.
Un modo corretto di implementare la funzione può essere il seguente:
Un modo corretto di implementare la funzione può essere il seguente:
void funzionelibero(link l) { if(l->successivo != NULL) { funzionelibero(l->successivo); } free(l); }
Grazie per la dritta, non ci avevo proprio fatto caso!!
Tutte le versione finora proposte hanno il difetto di assumere che il puntatore passato alla funzione sia non nulla. In alcuni casi credo possa avere senso, ma in questo caso stai facendo il test in ogni caso. Tanto vale fare quindi qualcosa come segue:
void funzionelibero(link l) { if (l == NULL) { return; } funzionelibero(l->successivo); free(l); }
"apatriarca":
Tutte le versione finora proposte hanno il difetto di assumere che il puntatore passato alla funzione sia non nulla.
Perché difetto? Se so in anticipo che passerò il puntatore al primo elemento.. ma poi che senso ha passare puntatore che punta a NULL? Chi lo farebbe? Nel senso, potrebbe essere un possibile problema del tipo che qualcuno potrebbe farlo per far crashare il programma o altro?
Un puntatore a NULL rappresenta nel tuo caso una lista vuota. Non si tratta quindi di un caso così strano o particolare. Si può insomma partire da un puntatore nullo e poi allocare il nodo solo quando si ha bisogno di aggiungere qualcosa. In questi casi, o aggiungi un test prima di chiamare la funzione o cambi il test dentro la funzione come ho scritto. A mio parere, ha senso evitare test del genere solo se il codice diventa più semplice o efficiente. In questo caso non c'è alcun vantaggio.
Aaah non avevo considerato gli altri casi effettivamente, hai ragione. Grazie!!!