Here's an example C program, in a file called a.c, with a memory error
and a memory leak.
It's worth fixing errors in the order they are reported, as
later errors can be caused by earlier errors. Failing to do this is a
common cause of difficulty with Memcheck.
Memory leak messages look like this:
There are several kinds of leaks; the two most important categories are:
Memcheck also reports uses of uninitialised values, most commonly with the message "Conditional jump or move depends on uninitialised value(s)". It can be difficult to determine the root cause of these errors. Try using the
#include <stdlib.h> void f(void) { int* x = malloc(10 * sizeof(int)); x[10] = 0; // problem 1: heap block overrun } // problem 2: memory leak -- x not freed int main(void) { f(); return 0; }
Most error messages look like the following, which describes problem 1, the heap block overrun:
==19182== Invalid write of size 4 ==19182== at 0x804838F: f (example.c:6) ==19182== by 0x80483AB: main (example.c:11) ==19182== Address 0x1BA45050 is 0 bytes after a block of size 40 alloc'd ==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130) ==19182== by 0x8048385: f (example.c:5) ==19182== by 0x80483AB: main (example.c:11)
Things to notice:
- There is a lot of information in each error message; read it carefully.
- The 19182 is the process ID; it's usually unimportant.
- The first line ("Invalid write...") tells you what kind of error it is. Here, the program wrote to some memory it should not have due to a heap block overrun.
- Below the first line is a stack trace telling you where the
problem occurred. Stack traces can get quite large, and be
confusing, especially if you are using the C++ STL. Reading them
from the bottom up can help. If the stack trace is not big enough,
use the
--num-callers
option to make it bigger. - The code addresses (eg. 0x804838F) are usually unimportant, but occasionally crucial for tracking down weirder bugs.
- Some error messages have a second component which describes the memory address involved. This one shows that the written memory is just past the end of a block allocated with malloc() on line 5 of example.c.
Memory leak messages look like this:
==19182== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130) ==19182== by 0x8048385: f (a.c:5) ==19182== by 0x80483AB: main (a.c:11)
The stack trace tells you where the leaked memory was allocated. Memcheck cannot tell you why the memory leaked, unfortunately. (Ignore the "vg_replace_malloc.c", that's an implementation detail.)
There are several kinds of leaks; the two most important categories are:
- "definitely lost": your program is leaking memory -- fix it!
- "probably lost": your program is leaking memory, unless you're doing funny things with pointers (such as moving them to point to the middle of a heap block).
Memcheck also reports uses of uninitialised values, most commonly with the message "Conditional jump or move depends on uninitialised value(s)". It can be difficult to determine the root cause of these errors. Try using the
--track-origins=yes
to get extra information.
This makes Memcheck run slower, but the extra information you get often
saves a lot of time figuring out where the uninitialised values are coming
from.