Debugging & Tooling

Valgrind and memcheck

/ Valgrind -> VAL-grind (rhymes with 'pal-grinned') /

Memory bugs in C are sneaky: you can read past the end of an array, use memory after freeing it, or forget to free it, and the program often keeps running fine - until much later, somewhere unrelated, it crashes or gives wrong answers. You need a watchful inspector who notices the very moment you touch memory you should not. Valgrind is that inspector. You run your program 'inside' Valgrind, and its tool memcheck watches every memory operation and reports the exact line where you misbehaved.

Concretely, Valgrind is a framework that runs your program on a simulated CPU: it does not just launch your binary, it interprets every machine instruction, inserting checks around each memory access. The default tool, memcheck, tracks which bytes of memory are addressable (you are allowed to touch them) and which are initialized (they hold a value you wrote). When your program reads or writes outside a valid block, reads memory that was never initialized, uses a pointer after free(), or frees the same block twice, memcheck catches it on the spot and prints the error with a stack trace pointing at the offending line. At the end it also reports leaks: blocks you allocated but never freed and can no longer reach. The price is speed: because every instruction is interpreted and instrumented, programs run roughly 10 to 50 times slower under Valgrind.

Why it matters: Valgrind/memcheck finds whole classes of memory bugs - use-after-free, buffer overflows, uninitialized reads, leaks, double frees - without recompiling, often turning a baffling 'crashes randomly' into 'invalid read of 4 bytes at line 88, inside a block freed at line 71'. Honest caveats: it is slow, so it is for testing, not production; it instruments the binary at run time rather than understanding your source, so it reports the symptom location which may be far from the cause; and it cannot find bugs on code paths your test run never exercises. For pure speed and some bug classes it has largely been complemented by the compiler sanitizers, which instrument at compile time and run much faster.

$ valgrind ./a.out on a program that reads one past a 10-element array prints something like: 'Invalid read of size 4 ... at main.c:14' and, at the end, 'definitely lost: 40 bytes in 1 blocks' for memory you malloc'd but never freed - both with exact lines.

Valgrind catches an out-of-bounds read and a leak, each with the exact source line.

Valgrind runs the unmodified binary on a simulated CPU, so it needs no recompile but is 10 to 50 times slower - fine for tests, not for production. It reports where the bad access happened, which can be far from the logic mistake that set up the bad pointer.

Also called
memcheckmemory error detector記憶體錯誤偵測器