Using valgrind

valgrind is a tool for finding memory access errors to heap memory (memory that is dynamically allocated with new or malloc) in C and C++ programs. Memory access errors are the most difficult bugs to find and to fix. Tools like valgrind can save you days worth of debugging time by quickly pointing you to the source and type of memory access errors in your code. The types of errors it can find include memory leaks, reading uninitialized memory, accessing unallocated memory, and array out-of-bounds errors.

Valgrind also includes a set of useful profiling tools, including the cache, heap and callgraph profilers valgrid tools. Documentation for these tools is here: valgrind tools docs

In /home/newhall/public/valgrind_examples/ is an example program with bad memory access errors (comments in the code describe the type of error). You can try out valgrind on this program to get an idea of how it works and what types of errors it can find.

Links to on-line valgrind help pages


How to use valgrind on our system

Running valgrind is easy. Just compile your program with -g, then run the executable (for non-interactive programs, you will likely want to re-direct output to a file since valgrind can generate a lot of output):
  % valgrind -v ./a.out 

  % valgrind -v ./a.out >& out   # re-direct valgrind (and a.out) output to file 'out'

If you look through the out file, you may see memory errors listed like this (each line of valgrind output starts with ==processid==):

==9860== Invalid write of size 1
==9860==    at 0x8048532: foo (main.c:28)
==9860==    by 0x804859F: main (main.c:48)
==9860==    by 0x4023514E: __libc_start_main (in /lib/libc-2.2.5.so)
==9860==    by 0x80483D0: (within /home/newhall/public/purify_examples/badprog)
==9860==    Address 0x40F33061 is 0 bytes after a block of size 5 alloc'd
==9860==    at 0x401678B8: malloc (vg_clientfuncs.c:103)
==9860==    by 0x80484C8: foo (main.c:17)
==9860==    by 0x804859F: main (main.c:48)
==9860==    by 0x4023514E: __libc_start_main (in /lib/libc-2.2.5.so)
This tells me that in function foo, at line 28 in main.c, my program is writing 1 byte beyond the array that was allocated at line 17 in function foo (9860 was the process ID of my running program). If I look at lines 17 and 28 of my program, the error is obvious (my loop executes one to many times, accessing c[5], which is beyond the end of array c, on the last iteration):
17         c = (char *)malloc(sizeof(char)*5);
18         strcpy(c, "cccc");
19 
...
27         for(i=0;  i <= 5; i++) {
28                 c[i] = str[i];
29	   }

valgrind Links

Valgrind manual (local copy) includes complete users manual
valgrind HOWTO See the "Usage" section for more information on using valgrind.

purify is another memory debugging tool. We do not have it installed on our system, but you can read about it here: purify