2016-05-31: The /* Programming Comments */ documents have moved, and will no longer be updated or maintained at this location! Please update your bookmarks: http://www.ccoderun.ca/programming/.


If you write C or C++ code in Linux, then you must know about and make regular use of the open-source Valgrind project. In my experience, nothing is better at finding file leaks, socket leaks, memory leaks, and memory corruption. All non-trivial software packages have various surprises; Valgrind will help you find a large portion of those surprises before it costs you valuable time and money.

Also see a follow-up post on Valgrind on 2013-12-01.

Here is what you need to know to use Valgrind for the first time:

How to install Valgrind

To install Valgrind bring up the Synaptic package manager, or run this command from the CLI: sudo apt-get install valgrind.

How to find leaks with Valgrind

Valgrind does a lot of things, and not all of them are enabled by default. Given the example code, here is the command to compile the example and run Valgrind:

g++ -ggdb 2010-01-09_Valgrind.cpp valgrind --leak-resolution=high --track-fds=yes --leak-check=full --show-reachable=yes ./a.out

Note that if possible, you want debugging enabled (g++ -ggdb ...) when you compile and link. Otherwise Valgrind will report the errors, but cannot say on which line the error occurred.

Line-by-line example output

This is what Valgrind reports:

Write past the end of the allocation block

==11781== Invalid write of size 1 ==11781== at 0x400722: main (2010-01-09_Valgrind.cpp:27) ==11781== Address 0x5944046 is 1 bytes after a block of size 5 alloc'd ==11781== at 0x4C255E4: operator new[](unsigned long) (vg_replace_malloc.c:264) ==11781== by 0x400715: main (2010-01-09_Valgrind.cpp:24)

Note the code leading up to line #27:

26 // array goes from 0-4, but we'll try to write to index [6] 27 p[6] = '\0';

Incorrect de-allocation

==11781== Mismatched free() / delete / delete [] ==11781== at 0x4C24A7A: operator delete(void*) (vg_replace_malloc.c:346) ==11781== by 0x400730: main (2010-01-09_Valgrind.cpp:30) ==11781== Address 0x5944040 is 0 bytes inside a block of size 5 alloc'd ==11781== at 0x4C255E4: operator new[](unsigned long) (vg_replace_malloc.c:264) ==11781== by 0x400715: main (2010-01-09_Valgrind.cpp:24)

Note the code leading up to line #30:

29 // allocation was for an array of chars so we should be calling delete [] p 30 delete p;

File descriptor leaks

==11781== Open file descriptor 3: test.txt ==11781== at 0x56A66B0: __open_nocancel (in /lib/libc-2.10.1.so) ==11781== by 0x56478FE: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:231) ==11781== by 0x563BDD5: __fopen_internal (iofopen.c:93) ==11781== by 0x40074D: main (2010-01-09_Valgrind.cpp:36)

The file handle obtained on line #36 is never released:

35 // open a file, but forget to close it 36 FILE *f = fopen( "test.txt", "w" );

Memory leaks

==11781== 10 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==11781== at 0x4C255E4: operator new[](unsigned long) (vg_replace_malloc.c:264) ==11781== by 0x40073A: main (2010-01-09_Valgrind.cpp:33) ==11781== ==11781== 568 bytes in 1 blocks are still reachable in loss record 2 of 2 ==11781== at 0x4C25153: malloc (vg_replace_malloc.c:195) ==11781== by 0x563BD7A: __fopen_internal (iofopen.c:76) ==11781== by 0x40074D: main (2010-01-09_Valgrind.cpp:36)

The two memory leaks are expected. The first is the explicit allocation on line 33 which is never freed:

32 // allocate a block and forget to free it 33 p = new char[10];

The second one is due to the fopen() call with no corresponding call to fclose().


Valgrind unfortunately does not detect problems with arrays on the stack. For example, this incorrect code is not flagged as a memory overwrite by Valgrind:

// write past the end of an array that was not dynamically allocated; // note that valgrind does not detect this kind of error char array[5]; strcpy( array, "testing" );

Lastly, note that Valgrind is more-or-less specific to Linux. The Valgrind team has no plans to port to Windows:

In particular Windows is not under consideration here because porting to it would require so many changes it would almost be a separate project.
Last modified: 2014-09-28
Stéphane Charette, stephanecharette@gmail.com