[C] memory leaks ed uso di free
Salve, sto cercando di capire meglio cosa sia un memory leak e come usare la funzione free correttamente.
Sto usando valgrind su ubuntu per vedere se i programmi possano contenere questi leaks; il codice parziale è questo:
|139|
La lista e':
139-->NULL
Dalla coda':
139-->NULL
==9644==
==9644== HEAP SUMMARY:
==9644== in use at exit: 24 bytes in 1 blocks
==9644== total heap usage: 2 allocs, 1 frees, 1,048 bytes allocated
==9644==
==9644== LEAK SUMMARY:
==9644== definitely lost: 24 bytes in 1 blocks
==9644== indirectly lost: 0 bytes in 0 blocks
==9644== possibly lost: 0 bytes in 0 blocks
==9644== still reachable: 0 bytes in 0 blocks
==9644== suppressed: 0 bytes in 0 blocks
==9644== Rerun with --leak-check=full to see details of leaked memory
==9644==
==9644== For lists of detected and suppressed errors, rerun with: -s
==9644== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Sto usando valgrind su ubuntu per vedere se i programmi possano contenere questi leaks; il codice parziale è questo:
void printTesta(list* l) { if(!l->head) { puts("La lista e' vuota\n"); } else { puts("\nLa lista e':\n"); while(l->head) { printf("%d-->", l->head->data); l->head =l->head->next; } puts("NULL\n"); } } void printCoda(list* l) { if(!l->tail) { puts("La lista e' vuota\n"); } else { puts("\nDalla coda':\n"); while(l->tail) { printf("%d-->", l->tail->data); l->tail = l->tail->prev; } puts("NULL\n"); } } void init(list* l) { l->head = l->tail = NULL; } list arrayToDoubleList(int * array, unsigned int dim) { if(dim == 0) { list l; init(&l); return l; } list l = arrayToDoubleList(array, dim - 1); insert(&l, array[dim -1]); return l; } int main() { srand(time(0)); unsigned int i, dim = rand()% 10; int array[dim]; for(i = 0; i < dim; i++) { array[i] = rand()% 300; printf("|%d|", array[i]); } list l = arrayToDoubleList(array, dim); printTesta(&l); printCoda(&l); }
|139|
La lista e':
139-->NULL
Dalla coda':
139-->NULL
==9644==
==9644== HEAP SUMMARY:
==9644== in use at exit: 24 bytes in 1 blocks
==9644== total heap usage: 2 allocs, 1 frees, 1,048 bytes allocated
==9644==
==9644== LEAK SUMMARY:
==9644== definitely lost: 24 bytes in 1 blocks
==9644== indirectly lost: 0 bytes in 0 blocks
==9644== possibly lost: 0 bytes in 0 blocks
==9644== still reachable: 0 bytes in 0 blocks
==9644== suppressed: 0 bytes in 0 blocks
==9644== Rerun with --leak-check=full to see details of leaked memory
==9644==
==9644== For lists of detected and suppressed errors, rerun with: -s
==9644== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Risposte
Suppongo che la dimensione di un nodo nel tuo programma sia 24 byte. Nel tuo codice hai allocato tale nodo contenente il numero 139 e poi non hai deallocato la memoria per cui questa memoria è "persa". Valgrind ti sta in effetti informando di questo problema.
ok credo di aver capito: ogni volta che vengono stampati gli elementi dalla coda bisogna fare in modo analogo alla cancellazione di un nodo; cioè utilizzando un puntatore temporaneo, mentre stupidamente io chiamavo la free subito dopo la printf perdendo il riferimento a tail:
|118||235||54||273|
La lista e':
54-->118-->235-->273-->NULL
Dalla coda':
273-->235-->118-->54-->NULL
==12974==
==12974== HEAP SUMMARY:
==12974== in use at exit: 0 bytes in 0 blocks
==12974== total heap usage: 5 allocs, 5 frees, 1,120 bytes allocated
==12974==
==12974== All heap blocks were freed -- no leaks are possible
==12974==
==12974== For lists of detected and suppressed errors, rerun with: -s
==12974== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
void printCoda(list* l) { if(!l->tail) { puts("La lista e' vuota\n"); } else { puts("\nDalla coda':\n"); while(l->tail) { printf("%d-->", l->tail->data); node* temp = l->tail; l->tail = l->tail->prev; free(temp); } puts("NULL\n"); } } void init(list* l) { l->head = l->tail = NULL; }Ovviamente sarebbe meglio utilizzare una funzione che faccia lo stesso, così non si è limitati dal modo in cui è scritto il codice(cioè se stampasi la lista in ordine inverso, dalla testa non avrei più valori).
|118||235||54||273|
La lista e':
54-->118-->235-->273-->NULL
Dalla coda':
273-->235-->118-->54-->NULL
==12974==
==12974== HEAP SUMMARY:
==12974== in use at exit: 0 bytes in 0 blocks
==12974== total heap usage: 5 allocs, 5 frees, 1,120 bytes allocated
==12974==
==12974== All heap blocks were freed -- no leaks are possible
==12974==
==12974== For lists of detected and suppressed errors, rerun with: -s
==12974== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
La deallocazione dovrebbe essere fatta in una funzione a parte e non nella stampa. In effetti la stampa non dovrebbe fare alcuna modifica alla lista.