Reputation: 34350
Would someone be able to shed light on why Valgrind classifies this program as a "Definitely Lost: 2 bytes in 1 block" memory leak? I understand that the commented line resolves the issue, but I don't understand the classification. According to Valgrind docs it appears that the memory leak should be classified as "Indirectly Reachable". I am also curious as to why this is even considered a memory leak and would appreciate an explanation. Is it good practice to manually free everything even though the program is terminating at the end of the main
function?
#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;
}
Here is the Valgrind output:
$ 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)
Upvotes: 6
Views: 6950
Reputation: 34350
Thanks to @sharth for pointing me in the right direction. The Direct Loss was actually properly detected by Valgrind, but was confusing due to the -O3
compilation which removed root
entirely. Compiling without -O3
shows the proper direct loss of 8 bytes and indirect loss of 2 bytes.
Also, thanks to @SylvainL and @Lundin for their best practices comments.
FYI: The corrected Valgrind output looks like this:
==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)
Upvotes: 2
Reputation: 3938
strdup allocates memory on the heap (using malloc) and therefore you need to free this memory when it's no longer in use like for anyone of your own direct call to malloc.
You must do that even when the program finish because this is the only way to detect a memory leak. Of course, the notion of checking for any memory leak might seem a little overkill when a program finish because all of its allocated memory is then automatically released by the OS but don't forget that your small program is an exception here. Usually, most programs will take a very large amount of memory when running and might run out of memory or run much slower if there are multiple memory leaks inside them.
Even a small program should be well written; otherwise it will become impossible for you to write any big programs later because your bad habits will translate into a tons of coding errors.
Upvotes: 3