2014-09-23 3 views
6

Würde jemand in der Lage sein zu beleuchten, warum Valgrind dieses Programm als "definitiv verloren: 2 Bytes in 1 Block" Speicherleck einordnet? Ich verstehe, dass die kommentierte Zeile das Problem löst, aber ich verstehe die Klassifizierung nicht. Laut Valgrind-Dokumenten scheint das Speicherleck als "Indirectally Reachable" (Indirekt erreichbar) zu gelten. Ich bin auch neugierig, warum dies sogar als ein Speicherleck gilt und würde eine Erklärung schätzen. Ist es eine gute Übung, alles manuell freizugeben, obwohl das Programm am Ende der main-Funktion endet?Definitiv verlorene Speicherleck in C-Programm

#include <stdlib.h> 

struct wrapper { 
    char *data; 
}; 

char *strdup(const char *); 

struct wrapper *walloc(struct wrapper *root) 
{ 
    if (root == NULL){ 
    root = (struct wrapper *) malloc(sizeof(struct wrapper)); 
    root->data = strdup("H"); 
    } 

    return root; 
} 

int main(){ 
    struct wrapper *root; 

    root = NULL; 
    root = walloc(root); 

    //free(root->data); 

    return 0; 
} 

ist der Valgrind Ausgang:

$ valgrind --leak-check=full ./leak 
==26489== Memcheck, a memory error detector 
==26489== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==26489== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==26489== Command: ./leak 
==26489== 
==26489== 
==26489== HEAP SUMMARY: 
==26489==  in use at exit: 2 bytes in 1 blocks 
==26489== total heap usage: 2 allocs, 1 frees, 1,790 bytes allocated 
==26489== 
==26489== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==26489== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==26489== by 0x4EB79C9: strdup (in /usr/lib/libc-2.20.so) 
==26489== by 0x400542: walloc (leak.c:13) 
==26489== by 0x400542: main (leak.c:23) 
==26489== 
==26489== LEAK SUMMARY: 
==26489== definitely lost: 2 bytes in 1 blocks 
==26489== indirectly lost: 0 bytes in 0 blocks 
==26489==  possibly lost: 0 bytes in 0 blocks 
==26489== still reachable: 0 bytes in 0 blocks 
==26489==   suppressed: 0 bytes in 0 blocks 
==26489== 
==26489== For counts of detected and suppressed errors, rerun with: -v 
==26489== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 
+2

„Ist es gute Praxis manuell frei alles, auch wenn das Programm am Ende der Hauptfunktion beendet?“ Ja, tun Sie das immer, auch wenn das Betriebssystem den Speicher freigibt. 'free()' kann Fehler in Ihrem Programm aufdecken, die sonst nur schwer zu finden sind. Es ist eine gute Angewohnheit, die De-Allocation immer direkt nach dem Zuweisen des Zuordnungscodes zu implementieren. – Lundin

+2

Ich sehe das nicht. Ich sehe 8 Bytes definitiv verloren ('root') und 2 Bytes indirekt verloren (' root-> data'). Kannst du die volle Ausgabe von Valgrind posten? –

+0

Sie sollten '#include ' da der Compiler ist dann erlaubt, "magische" Dinge mit 'strdup' (und [GCC] (http://gcc.gnu.org/) tut manchmal) –

Antwort

2

Danke an @sharth, dass Sie mich in die richtige Richtung weisen. Der direkte Verlust wurde von Valgrind korrekt erkannt, war aber aufgrund der -O3 Zusammenstellung, die root vollständig entfernte, verwirrend. Kompilieren ohne -O3 zeigt den richtigen direkten Verlust von 8 Bytes und indirekten Verlust von 2 Bytes.

Auch dank @SylvainL und @Lundin für ihre Best Practices Kommentare.

Zur Info: Die korrigierte Valgrind Ausgabe sieht wie folgt aus:

==30492== Memcheck, a memory error detector 
==30492== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==30492== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==30492== Command: ./leak 
==30492== 
==30492== 
==30492== HEAP SUMMARY: 
==30492==  in use at exit: 10 bytes in 2 blocks 
==30492== total heap usage: 3 allocs, 1 frees, 1,830 bytes allocated 
==30492== 
==30492== 10 (8 direct, 2 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2 
==30492== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30492== by 0x400687: walloc (leak.c:12) 
==30492== by 0x4006C6: main (leak.c:23) 
==30492== 
==30492== LEAK SUMMARY: 
==30492== definitely lost: 8 bytes in 1 blocks 
==30492== indirectly lost: 2 bytes in 1 blocks 
==30492==  possibly lost: 0 bytes in 0 blocks 
==30492== still reachable: 0 bytes in 0 blocks 
==30492==   suppressed: 0 bytes in 0 blocks 
==30492== 
==30492== For counts of detected and suppressed errors, rerun with: -v 
==30492== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 
3

strdup Speicher auf dem Heap reserviert (malloc) und daher müssen Sie diesen Speicher frei wenn es wie jedem Ihrer eigenen nicht mehr in Gebrauch ist direkter Anruf zu malloc.

Sie müssen dies selbst dann tun, wenn das Programm beendet wird, da dies die einzige Möglichkeit ist, ein Speicherleck zu erkennen. Natürlich scheint die Idee, nach einem Speicherleck zu suchen, ein wenig übertrieben zu sein, wenn ein Programm beendet wird, da der gesamte zugewiesene Speicher dann automatisch vom Betriebssystem freigegeben wird, aber vergessen Sie nicht, dass Ihr kleines Programm hier eine Ausnahme darstellt. In der Regel benötigen die meisten Programme sehr viel Speicher, wenn sie ausgeführt werden, und haben möglicherweise nicht genügend Arbeitsspeicher oder laufen viel langsamer, wenn in ihnen mehrere Speicherlecks vorhanden sind.

Selbst ein kleines Programm sollte gut geschrieben sein; sonst wird es für Sie unmöglich, später irgendwelche großen Programme zu schreiben, weil Ihre schlechten Angewohnheiten zu einer Unmenge von Codierungsfehlern führen.

+0

Danke für die Antwort. Warum meldet Valgrind dies als Direct Leak, wenn die Zeichenfolge in einer Struktur verschachtelt ist? Auch warum beschwert sich Valgrind nicht darüber, den für "root" reservierten Speicher freizugeben? –

+0

Tut mir leid, ich benutze Valgrind nicht und daher habe ich keine Ahnung von den verschiedenen Definitionen, die es verwendet. Vielleicht ist der für root reservierte Speicher ein sogenannter "Loss Record", aber Sie sollten die Dokumentation überprüfen oder in einem Forum nach Valgrind fragen oder eine andere Frage speziell zu Valgrind stellen. – SylvainL