Small Valgrind introduction
Everyone writing C or C++ code should know what a memory leak is. You allocate some memory, and never free it.
It can be very hard to make your code memleak free, or even just to know whether your code contains any memleaks.
Luckily, in the Free Software world, we got a great tool to check our code for memleaks (or other errors): Valgrind.
As I don't have time to write a lot now, I'll just give a very simple sample of it's usage.
Here's my code (very bad code, obviously, but hey ;-)):
#include <stdio.h>
#include <stdlib.h>
static void function() {
char *test = (char *)malloc(100 * sizeof(char));
test[0] = '\0';
printf("Function\n");
/* Leaking 100 chars here, 100 bytes */
}
int main(int argc, char *argv[]) {
int *i = NULL;
function();
i = (int *)malloc(50 * sizeof(int));
printf("Done\n");
return 0;
/* Leaking 50 ints here. On x86, this is 50*4=200 bytes */
}
As you can see, we leak memory twice: once 100 bytes, once 200.
Let's compile and run our code:
$ gcc -o test -Wall -g test.c
$ ./test
Function
Done
Great, our code works fine (or at least, it looks like it).
Now we introduce valgrind. First we'll do a simple memory allocation check:
$ valgrind --tool=memcheck ./test ==18819== Memcheck, a memory error detector for x86-linux.
==18819== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==18819== Using valgrind-2.2.0, a program supervision framework for x86-linux.
==18819== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==18819== For more details, rerun with: -v
==18819==
Function
Done
==18819==
==18819== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
==18819== malloc/free: in use at exit: 300 bytes in 2 blocks.
==18819== malloc/free: 2 allocs, 0 frees, 300 bytes allocated.
==18819== For a detailed leak analysis, rerun with: --leak-check=yes
==18819== For counts of detected errors, rerun with: -v
Valgrind tells us we leaked 300 bytes, in 2 blocks (one malloc call returns one block, obviously).
It also tells us to re-run the test with the --leak-check=yes flag, which is a good advice:
$ valgrind --tool=memcheck --leak-check=yes ./test
==18826== Memcheck, a memory error detector for x86-linux.
==18826== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==18826== Using valgrind-2.2.0, a program supervision framework for x86-linux.
==18826== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==18826== For more details, rerun with: -v
==18826==
Function
Done
==18826==
==18826== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
==18826== malloc/free: in use at exit: 300 bytes in 2 blocks.
==18826== malloc/free: 2 allocs, 0 frees, 300 bytes allocated.
==18826== For counts of detected errors, rerun with: -v
==18826== searching for pointers to 2 not-freed blocks.
==18826== checked 1404368 bytes.
==18826==
==18826== 100 bytes in 1 blocks are definitely lost in loss record 1 of 2
==18826== at 0x1B906B82: malloc (vg_replace_malloc.c:131)
==18826== by 0x80483B5: function (test.c:5)
==18826== by 0x80483F4: main (test.c:14)
==18826==
==18826==
==18826== 200 bytes in 1 blocks are definitely lost in loss record 2 of 2
==18826== at 0x1B906B82: malloc (vg_replace_malloc.c:131)
==18826== by 0x8048400: main (test.c:15)
==18826==
==18826== LEAK SUMMARY:
==18826== definitely lost: 300 bytes in 2 blocks.
==18826== possibly lost: 0 bytes in 0 blocks.
==18826== still reachable: 0 bytes in 0 blocks.
==18826== suppressed: 0 bytes in 0 blocks.
==18826== Reachable blocks (those to which a pointer was found) are not shown.
==18826== To see them, rerun with: --show-reachable=yes
Great, here Valgrind tells us exactly what we're doing wrong.
There are 2 blocks where we leak memory:
The first one is at code path
main (test.c:14) -> function (test.c:5) -> malloc (vg_replace_malloc.c:131)
leaking 100 bytes.
The vg_replace_malloc.c file isn't ours, it's a valgrind file where the malloc() wrapper (which keeps track of our allocations/free's/...) is located. We're mostly interested in the "function (test.c:5)" part. If we look at line 5, we see this is
char *test = (char *)malloc(100 * sizeof(char));
our first allocation. And indeed, if we look further, we never free these 100 chars.
- Second is at main (test.c:15). Again, we can look at this line:
i = (int *)malloc(50 * sizeof(int));
and indeed, we never free these allocated integers again. We allocated 50 ints, and on x86 one int is 32 bits (4 bytes), so we leak 200 bytes (and valgrind was correct once again :-)).
Obviously, valgrind got much more options or checks:
$ valgrind
valgrind: Missing --tool option
Available tools:
memcheck
addrcheck
cachegrind
corecheck
helgrind
massif
lackey
none
callgrind
valgrind: Use --help for more information.
I don't know all of them, actually I only use the memcheck thing, but even when only using one tool, it can be a very useful program.
I got one minor issue with valgrind currently: when it detects memory leaks in some program, it still returns 0 in the end, so it's not easy to integrate valgrind checks in automake's "make check" target. If someone got any pointers how to do this, please let me know!