Perdita ancora raggiungibile rilevata da Valgrind

Tutte le funzioni menzionate in questo blocco sono funzioni di libreria. Come posso correggere questa perdita di memoria?

È elencato nella categoria ” Ancora raggiungibile “. (Ce ne sono altri 4, che sono molto simili, ma di varie dimensioni)

630 bytes in 1 blocks are still reachable in loss record 5 of 5 at 0x4004F1B: calloc (vg_replace_malloc.c:418) by 0x931CD2: _dl_new_object (dl-object.c:52) by 0x92DD36: _dl_map_object_from_fd (dl-load.c:972) by 0x92EFB6: _dl_map_object (dl-load.c:2251) by 0x939F1B: dl_open_worker (dl-open.c:255) by 0x935965: _dl_catch_error (dl-error.c:178) by 0x9399C5: _dl_open (dl-open.c:584) by 0xA64E31: do_dlopen (dl-libc.c:86) by 0x935965: _dl_catch_error (dl-error.c:178) by 0xA64FF4: __libc_dlopen_mode (dl-libc.c:47) by 0xAE6086: pthread_cancel_init (unwind-forcedunwind.c:53) by 0xAE61FC: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126) 

Catch: una volta eseguito il mio programma, non ha dato perdite di memoria, ma aveva una riga aggiuntiva nell’output di Valgrind, che non era presente prima:

Scartare syms a 0x5296fa0-0x52af438 in /lib/libgcc_s-4.4.4-20100630.so.1 a causa di munmap ()

Se la perdita non può essere corretta, qualcuno può spiegare perché la linea munmap () fa sì che Valgrind riferisca a 0 perdite “ancora raggiungibili”?

Modificare:

Ecco un campione di prova minimo:

 #include  #include  #include  void *runner(void *param) { /* some operations ... */ pthread_exit(NULL); } int n; int main(void) { int i; pthread_t *threadIdArray; n=10; /* for example */ threadIdArray = malloc((n+n-1)*sizeof(pthread_t)); for(i=0;i<(n+n-1);i++) { if( pthread_create(&threadIdArray[i],NULL,runner,NULL) != 0 ) { printf("Couldn't create thread %d\n",i); exit(1); } } for(i=0;i<(n+n-1);i++) { pthread_join(threadIdArray[i],NULL); } free(threadIdArray); return(0); } 

Corri con:

 valgrind -v --leak-check=full --show-reachable=yes ./a.out 

C’è più di un modo per definire “perdita di memoria”. In particolare, esistono due definizioni principali di “perdita di memoria” che sono comunemente utilizzate dai programmatori.

La prima definizione comunemente usata di “perdita di memoria” è, “La memoria è stata allocata e non è stata successivamente liberata prima della fine del programma.” Tuttavia, molti programmatori (giustamente) sostengono che alcuni tipi di perdite di memoria che si adattano a questa definizione non pongono effettivamente alcun tipo di problema, e quindi non dovrebbero essere considerate vere “perdite di memoria”.

Una definizione probabilmente più restrittiva (e più utile) di “perdita di memoria” è, “La memoria è stata allocata e non può essere successivamente liberata perché il programma non ha più alcun riferimento al blocco di memoria assegnato.” In altre parole, non puoi liberare memoria a cui non hai più alcun suggerimento. Tale memoria è quindi una “perdita di memoria”. Valgrind utilizza questa definizione più rigorosa del termine “perdita di memoria”. Questo è il tipo di perdita che può potenzialmente causare un esaurimento dell’heap significativo, specialmente per processi a lunga durata.

La categoria “ancora raggiungibile” all’interno del rapporto sulle perdite di Valgrind fa riferimento a allocazioni che si adattano solo alla prima definizione di “perdita di memoria”. Questi blocchi non sono stati liberati, ma avrebbero potuto essere liberati (se il programmatore lo avesse voluto) perché il programma stava ancora tenendo traccia dei puntatori a quei blocchi di memoria.

In generale, non è necessario preoccuparsi dei blocchi “ancora raggiungibili”. Non rappresentano il tipo di problema che possono causare le vere perdite di memoria. Ad esempio, normalmente non esiste il potenziale per l’esaurimento dell’heap dai blocchi “ancora raggiungibili”. Questo perché questi blocchi sono solitamente allocazioni una tantum, i cui riferimenti sono mantenuti per tutta la durata della vita del processo. Mentre si può passare e assicurarsi che il programma libera tutta la memoria allocata, di solito non vi è alcun beneficio pratico dal momento che il sistema operativo recupera tutta la memoria del processo dopo che il processo termina, comunque. Confrontate questo con perdite di memoria reali che, se lasciate non fissate, potrebbero far sì che un processo esaurisca la memoria se viene lasciato funzionare abbastanza a lungo, o semplicemente causerà un processo per consumare molta più memoria di quanto sia necessario.

Probabilmente l’unica volta in cui è utile assicurarsi che tutte le allocazioni abbiano corrispondenze “libere” è se gli strumenti di rilevamento perdite non sono in grado di stabilire quali blocchi sono “ancora raggiungibili” (ma Valgrind può farlo) o se il sistema operativo non recupera tutto una memoria del processo di chiusura (tutte le piattaforms su cui è stato effettuato il porting di Valgrind).

Dato che c’è una routine dalla famiglia pthread in basso (ma non conosco quella particolare), suppongo che tu abbia lanciato alcuni thread come joinable che ha terminato l’esecuzione.

Le informazioni sullo stato di uscita di quel thread sono mantenute disponibili fino a quando non chiami pthread_join . Pertanto, la memoria viene mantenuta in un record di perdita al termine del programma, ma è comunque raggiungibile poiché è ansible utilizzare pthread_join per accedervi.

Se questa analisi è corretta, avviare questi thread separati o unirli prima di terminare il programma.

Modifica : ho eseguito il programma di esempio (dopo alcune correzioni ovvie) e non ho errori ma quanto segue

 ==18933== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) --18933-- --18933-- used_suppression: 2 dl-hack3-cond-1 --18933-- used_suppression: 2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a 

Dal momento che il dl- thing assomiglia molto a ciò che si vede, suppongo che si veda un problema noto che ha una soluzione in termini di un file di soppressione per valgrind . Forse il tuo sistema non è aggiornato, o la tua distribuzione non mantiene queste cose. (Il mio è ubuntu 10.4, 64bit)

Non sembri capire cosa sia still reachable .

Tutto ciò che è still reachable non è una perdita. Non devi fare nulla al riguardo.

Ecco una spiegazione corretta di “ancora raggiungibile”:

“Ancora raggiungibile” sono perdite assegnate a variabili globali e statiche locali. Poiché valgrind tiene traccia delle variabili globali e statiche, può escludere allocazioni di memoria assegnate “una volta e dimenticati”. Una variabile globale ha assegnato un’allocazione una volta e non ha mai riassegnato che l’allocazione non è in genere una “perdita” nel senso che non cresce indefinitamente. È ancora una perdita in senso stretto, ma di solito può essere ignorata a meno che tu non sia pedante.

Le variabili locali a cui sono assegnate allocazioni e non liberate sono quasi sempre perdite.

Ecco un esempio

 int foo(void) { static char *working_buf = NULL; char *temp_buf; if (!working_buf) { working_buf = (char *) malloc(16 * 1024); } temp_buf = (char *) malloc(5 * 1024); .... .... .... } 

Valgrind riporterà working_buf come “ancora raggiungibile – 16k” e temp_buf come “definitivamente perso – 5k”.