Valgrind
Overview
Tutorial: 45 min
- Objectives:
Understand the basics of Valgrind and how to use it for profiling applications.
Valgrind is a programming tool for memory debugging, memory leak detection, and profiling. It helps developers identify memory-related issues in their applications, such as memory leaks, uninitialized memory reads, and invalid memory accesses.
First, start an interactive job on the cluster
1qsub -I -q normal -P vp91 -l walltime=02:00:00 -l ncpus=48 -l mem=192GB -l wd
and load the necessary modules.
1module load gcc/15.1.0
Run Valgrind to detect memory leaks
Compile the code with debugging information
1cd /scratch/vp91/$USER/intro-to-profiling/code/valgrind
2gcc -g -O0 1_leak.c -o 1_leak
-g enables debugging information.
-O0 disables optimizations to make debugging easier.
Now run the program with Valgrind to check for memory leaks
1valgrind ./1_leak
This will produce output indicating any memory leaks detected in the program. Look for lines that mention “definitely lost” to identify memory that was allocated but not freed.
Sample output will be similar to:
1==384063== HEAP SUMMARY:
2==384063== in use at exit: 40 bytes in 1 blocks
3==384063== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
4==384063==
5==384063== LEAK SUMMARY:
6==384063== definitely lost: 40 bytes in 1 blocks
7==384063== indirectly lost: 0 bytes in 0 blocks
8==384063== possibly lost: 0 bytes in 0 blocks
9==384063== still reachable: 0 bytes in 0 blocks
10==384063== suppressed: 0 bytes in 0 blocks
11==384063== Rerun with --leak-check=full to see details of leaked memory
12==384063==
13==384063== For lists of detected and suppressed errors, rerun with: -s
14==384063== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Definitely lost: No pointer to the allocated memory exists at program exit. This a real memory leak that must be fixed.
Indirectly lost: Memory is only reachable through another leaked block. Fixing the definitely lost allocation will fix this too.
Possibly lost: A pointer exists but does not point to the start of the allocation → ambiguous, often caused by pointer arithmetic and usually a bug.
Still reachable: Memory is still referenced at exit and could be freed → not a true leak, typically safe to ignore.
Indirect leak example
Compile the code with debugging information
1cd /scratch/vp91/$USER/intro-to-profiling/code/valgrind
2
3gcc -g -O0 2_indirect.c -o 2_indirect
and run Valgrind
1valgrind ./2_indirect
Sample output will be similar to:
1==384410== HEAP SUMMARY:
2==384410== in use at exit: 48 bytes in 2 blocks
3==384410== total heap usage: 2 allocs, 0 frees, 48 bytes allocated
4==384410==
5==384410== LEAK SUMMARY:
6==384410== definitely lost: 8 bytes in 1 blocks
7==384410== indirectly lost: 40 bytes in 1 blocks
8==384410== possibly lost: 0 bytes in 0 blocks
9==384410== still reachable: 0 bytes in 0 blocks
10==384410== suppressed: 0 bytes in 0 blocks
Possibly lost example
Compile the code with debugging information
1cd /scratch/vp91/$USER/intro-to-profiling/code/valgrind
2
3gcc -g -O0 3_possible.c -o 3_possible
run Valgrind
1valgrind ./3_possible
Sample output will be similar to:
1==384772== HEAP SUMMARY:
2==384772== in use at exit: 100 bytes in 1 blocks
3==384772== total heap usage: 1 allocs, 0 frees, 100 bytes allocated
4==384772==
5==384772== LEAK SUMMARY:
6==384772== definitely lost: 0 bytes in 0 blocks
7==384772== indirectly lost: 0 bytes in 0 blocks
8==384772== possibly lost: 100 bytes in 1 blocks
9==384772== still reachable: 0 bytes in 0 blocks
10==384772== suppressed: 0 bytes in 0 blocks
Still reachable example
Comnpile the code with debugging information
1cd /scratch/vp91/$USER/intro-to-profiling/code/valgrind
2
3gcc -g -O0 4_still_reachable.c -o 4_still_reachable
Run Valgrind
1valgrind ./4_still_reachable
Sample output will be similar to:
1==384651== HEAP SUMMARY:
2==384651== in use at exit: 100 bytes in 1 blocks
3==384651== total heap usage: 1 allocs, 0 frees, 100 bytes allocated
4==384651==
5==384651== LEAK SUMMARY:
6==384651== definitely lost: 0 bytes in 0 blocks
7==384651== indirectly lost: 0 bytes in 0 blocks
8==384651== possibly lost: 0 bytes in 0 blocks
9==384651== still reachable: 100 bytes in 1 blocks
10==384651== suppressed: 0 bytes in 0 blocks
Detailed leak report
To see more details about the leaks, rerun Valgrind with the –leak-check=full option:
1cd /scratch/vp91/$USER/intro-to-profiling/code/valgrind
2
3gcc -g -O0 5_leaks_all.c -o 5_leaks_all
Run Valgrind
1valgrind --leak-check=full --show-leak-kinds=all ./5_leaks_all
–leak-check=full: provides detailed information about each memory leak.
–show-leak-kinds=all: shows all types of leaks: definitely lost, indirectly lost, possibly lost, and still reachable.
Sample output will be similar to:
1==384913== HEAP SUMMARY:
2==384913== in use at exit: 428 bytes in 5 blocks
3==384913== total heap usage: 5 allocs, 0 frees, 428 bytes allocated
4==384913==
5==384913== 40 bytes in 1 blocks are definitely lost in loss record 1 of 5
6==384913== at 0x4C39185: malloc (vg_replace_malloc.c:442)
7==384913== by 0x400617: main (5_leak_all.c:16)
8==384913==
9==384913== 80 bytes in 1 blocks are indirectly lost in loss record 2 of 5
10==384913== at 0x4C39185: malloc (vg_replace_malloc.c:442)
11==384913== by 0x400633: main (5_leak_all.c:21)
12==384913==
13==384913== 88 (8 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 5
14==384913== at 0x4C39185: malloc (vg_replace_malloc.c:442)
15==384913== by 0x400625: main (5_leak_all.c:20)
16==384913==
17==384913== 100 bytes in 1 blocks are possibly lost in loss record 4 of 5
18==384913== at 0x4C39185: malloc (vg_replace_malloc.c:442)
19==384913== by 0x400647: main (5_leak_all.c:25)
20==384913==
21==384913== 200 bytes in 1 blocks are still reachable in loss record 5 of 5
22==384913== at 0x4C39185: malloc (vg_replace_malloc.c:442)
23==384913== by 0x400664: main (5_leak_all.c:30)
24==384913==
25==384913== LEAK SUMMARY:
26==384913== definitely lost: 48 bytes in 2 blocks
27==384913== indirectly lost: 80 bytes in 1 blocks
28==384913== possibly lost: 100 bytes in 1 blocks
29==384913== still reachable: 200 bytes in 1 blocks
30==384913== suppressed: 0 bytes in 0 blocks
Key Points
Valgrind is a programming tool for memory debugging, memory leak detection, and profiling.
It helps identify memory-related issues in applications, such as memory leaks and invalid memory accesses.
Compile code with debugging information using the -g flag to get detailed reports from Valgrind.
Run Valgrind with the –leak-check=full option to see detailed information about memory leaks.
Understand the different types of memory leaks reported by Valgrind: definitely lost, indirectly lost, possibly lost, and still reachable.