valgrind(1)
Development tool
Runs your program while watching every memory access: invalid reads, uninitialized values, blocks that are never freed.
valgrind [options] program [arguments]Description
Valgrind runs your program on a simulated processor. Its default tool, Memcheck, intercepts every read, every write, every malloc and every free. It reports accesses outside the allocated blocks, uses of values that were never initialized, double frees, and at the end the memory still allocated. The program runs much more slowly; that is the price of this monitoring.
Compile with -g: without it, the reports give addresses instead of file names and line numbers.
Useful options
| Option | Effect |
|---|---|
--leak-check=full | details each leak with the line that allocated the block |
--show-leak-kinds=all | also shows the memory still reachable at exit |
--track-origins=yes | tells you where an uninitialized value comes from |
-q | prints only the errors |
Example
#include <stdlib.h>#include <string.h>
int main(void){ char *copy = malloc(16);
strcpy(copy, "leak"); return 0;}$ gcc -g leak.c -o leak$ valgrind --leak-check=full ./leak==14== Memcheck, a memory error detector==14== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.==14== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info==14== Command: ./leak==14== ==14== ==14== HEAP SUMMARY:==14== in use at exit: 16 bytes in 1 blocks==14== total heap usage: 1 allocs, 0 frees, 16 bytes allocated==14== ==14== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1==14== at 0x488545C: malloc (vg_replace_malloc.c:446)==14== by 0x400653: main (leak.c:6)==14== ==14== LEAK SUMMARY:==14== definitely lost: 16 bytes in 1 blocks...==14== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)The number at the start of each line is the process ID. The 16-byte block allocated on line 6 was never freed, and no pointer refers to it anymore: it is “definitely lost”.
Pitfalls
Valgrind only sees the path that actually runs. A test that does not go through the faulty code reports nothing.
It does not watch overruns inside the stack, such as an
int t[5]read att[5]. For those, compile with-fsanitize=address.On recent versions of macOS, Valgrind is not officially available. A Linux container, WSL or the terminal of a Grademe exercise will do.
read_the_leak
Fix build_path, which returns the right path but leaks one block per call: read the leak report, then free the block it borrowed.