Site Tools


wiki:valgrind

valgrind

What is Valgrind?

Valgrind is a dynamic analysis framework for finding memory errors and profiling program behaviour. Rather than reading source code statically, it runs the target program on a synthetic CPU it implements in software (a process called instrumentation), which lets it observe every single memory access and instruction the program executes and check it against a set of correctness rules.

C and C++ give the programmer direct control over memory, and with it, the ability to read past the end of an array, use memory after freeing it, or leak allocations that never get freed. These bugs often don't crash the program immediately; they corrupt state silently and crash somewhere unrelated much later, which makes them notoriously hard to find by inspection alone. Valgrind's memcheck tool catches the error at the moment it happens, not at the moment it eventually causes a visible symptom.

The cost of this precision is speed: instrumented execution under Valgrind typically runs 10-50x slower than native. That trade-off is fine for a correctness-checking run over a test suite but makes Valgrind unsuitable as a general profiler for production-scale workloads, where perf is the better tool.

Install

On Debian and Ubuntu:

sudo apt install valgrind

On Fedora and RHEL:

sudo dnf install valgrind

Compile the target with debug symbols so Valgrind's reports include source file and line numbers rather than raw addresses:

gcc -g -O0 -o app app.c

-O0 is recommended for memcheck runs; optimisation can reorder and merge memory accesses in ways that make Valgrind's line-number attribution less precise.

Practice

The default tool is memcheck, which is what most people mean when they say “run it under Valgrind”:

valgrind ./app

A leak or invalid access produces a report pointing at the offending allocation and, for leaks, the stack trace of the malloc call that never got freed:

==12345== Invalid read of size 4
==12345==    at 0x109179: process (app.c:22)
==12345==    by 0x1091AB: main (app.c:31)
==12345==  Address 0x4a4b080 is 0 bytes after a block of size 40 alloc'd
==12345==    at 0x483DD99: malloc (vg_replace_malloc.c:307)
==12345==    by 0x109150: process (app.c:15)

For a full leak summary with the allocation stack trace for every leaked block:

valgrind --leak-check=full --track-origins=yes ./app

--track-origins=yes adds a second stack trace showing where an uninitialised value originated, at the cost of extra slowdown; it's worth enabling when memcheck reports a “conditional jump depends on uninitialised value” error without an obvious cause.

Concepts

memcheck

memcheck tracks every byte of memory the program allocates and maintains shadow state for it: whether it's been initialised, whether it's still valid (not yet freed). It catches four main classes of error: reading or writing past an allocation's bounds, using memory after free, using uninitialised values in a way that affects program behaviour, and memory leaks.

valgrind --leak-check=full --show-leak-kinds=all ./app

--show-leak-kinds=all reports not just “definitely lost” blocks (unambiguous leaks) but also “possibly lost” and “still reachable” ones, useful for a thorough audit but noisier for everyday debugging.

helgrind and DRD

helgrind and DRD are Valgrind tools for detecting data races and lock-ordering problems in multithreaded programs (relevant to OpenMP and pthreads code), rather than memory errors:

valgrind --tool=helgrind ./threaded_app

helgrind reports when two threads access the same memory location without a happens-before relationship established by a lock or other synchronisation primitive, the definition of a data race, even if the race doesn't happen to produce a visibly wrong result on this particular run.

callgrind

callgrind is a profiling tool built on the same instrumentation engine, recording call graphs and per-function instruction counts rather than checking memory correctness:

valgrind --tool=callgrind ./app
callgrind_annotate callgrind.out.12345

Because it counts instructions deterministically rather than sampling, callgrind gives reproducible profiles even for very short-running programs where a sampling profiler like perf wouldn't collect enough samples, at the cost of the same order-of-magnitude slowdown as memcheck.

Suppressions

Valgrind can report false positives originating in system libraries or the language runtime rather than the program under test. A suppression file lists error patterns to ignore:

valgrind --suppressions=my_project.supp ./app

Most distributions ship a default suppression file for common libc and glibc false positives already; a project-specific suppression file is for known, accepted issues in third-party dependencies the project can't fix directly.

wiki/valgrind.md · Last modified: by 127.0.0.1