2010-08-21 24 views
27

Posso trattare l'output di un memo in Valgrind, "possibilmente perso" come "definitivamente perso"?Valgrind: può forse essere perso come definitivamente perso?

Forse perso o "dubbio": viene trovato un puntatore all'interno del blocco. Il puntatore potrebbe in origine indicare la partenza e sono stati spostati, oppure potrebbe non essere interamente correlato. Memcheck considera un blocco come "dubbio", perché non è chiaro se esiste ancora un puntatore .

Definitivamente perso o "filtrato": il risultato peggiore è che non è possibile trovare alcun puntatore al blocco. Il blocco è classificato come "trapelato", perché il programmatore non può averlo liberato all'uscita del programma , poiché non esiste alcun puntatore ad esso. Questo è probabilmente un sintomo di avendo perso il puntatore ad un certo punto in precedenza nel programma

risposta

45

Sì, vi consiglio per trattare forse perso così grave come sicuramente perso. In altre parole, correggi il tuo codice fino a quando non ci sono affatto perdite.

Possibile perdita può accadere quando si attraversa un array utilizzando lo stesso puntatore che lo trattiene. È sapere che è possibile ripristinare il puntatore sottraendo l'indice. Ma valgrind non può dire se si tratta di un errore di programmazione o sei intelligente fare questo deliberatamente. Questo è il motivo per cui ti avverte.

Esempio

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

int main(int argc, char** argv) { 
    char* s = "string"; 
    // this will allocate a new array 
    char* p = strdup(s); 
    // move the pointer into the array 
    // we know we can reset the pointer by subtracting 
    // but for valgrind the array is now lost 
    p += 1; 
    // deliberately trigger a segfault to crash the program 
    *s = 'S'; 
    // reset the pointer to the beginning of the array 
    p -= 1; 
    // properly free the memory for the array 
    free(p); 
    return 0; 
} 

Compile

$ gcc -ggdb foo.c -o foo 

rapporto Valgrind

$ valgrind ./foo 
... 
==3415== Command: ./foo 
==3415== 
==3415== 
==3415== Process terminating with default action of signal 11 (SIGSEGV) 
==3415== Bad permissions for mapped region at address 0x80484E0 
==3415== at 0x804840E: main (foo.c:14) 
==3415== 
==3415== HEAP SUMMARY: 
==3415==  in use at exit: 7 bytes in 1 blocks 
==3415== total heap usage: 1 allocs, 0 frees, 7 bytes allocated 
==3415== 
==3415== LEAK SUMMARY: 
==3415== definitely lost: 0 bytes in 0 blocks 
==3415== indirectly lost: 0 bytes in 0 blocks 
==3415==  possibly lost: 7 bytes in 1 blocks 
==3415== still reachable: 0 bytes in 0 blocks 
==3415==   suppressed: 0 bytes in 0 blocks 
... 

Se si rimuove la linea causando la segfault poi Valgrind segnalerà senza memoria perduta a tutti. Senza segfault, il puntatore tornerà all'inizio dell'array e la memoria sarà free d correttamente.

Questo è un esempio banale. In un codice sufficientemente complicato non è più ovvio che il puntatore possa e tornerà all'inizio del blocco di memoria. Modifiche nell'altra parte del codice possono causare il possibilmente perso per essere un definitivamente perso. Questo è il motivo per cui dovresti preoccuparti di eventualmente perso.

+0

grazie lesmana per una spiegazione dettagliata. –