You are on page 1of 14

Tutorial: Valgrind

CS447/CS647/ECE453/ECE653/SE465
Lei Zhang
lei.zhang@uwaterloo.ca
2014-2-14
What is Valgrind
Valgrind is a GPL'd system for debugging and
profiling Linux programs. With Valgrind's tool
suite you can automatically detect many
memory management and threading bugs,
avoiding hours of frustrating bug-hunting,
making your programs more stable. You can also
perform detailed profiling to help speed up your
programs.
-- http://valgrind.org/info/
Valgrind Tool Suite
An instrumentation framework for building
dynamic analysis tools
Memcheck: memory error detector
Cachegrind: cache profiler
Helgrind, DRD: thread error detectors
Massif: heap profiler
...
Memcheck
Intercept calls to malloc/new/free/delete
Check all reads and writes of memory
Detect memory-management problems
buffer overflow
memory leak
allocation/deallocation mismatch
R/W via dangling pointer
use uninitialized memory
...
A Bit of Internals
Valgrind is essentially a virtual machine
Translate machine code into an architecture-
independent intermediate representation
Insert instrumentation code around the IR
(depending on the tool)
Translating back into machine code and run
on a simulated CPU
Memcheck: every register/memory value has a
shadow value containing information about it
Get Valgrind
Install Valgrind
ecelinux has Valgrind pre-installed
Ubuntu: apt-get install valgrind
Archlinux: pacman -S valgrind
General: ./configure & make & make install
Use Memcheck to Debug
Compile your program
$ gcc -g example.c -o example
-g: include debug info. so Valgrind knows line #
-O: optimization, -O2 and above can screw up
Valgrind report, not recommended
Run Valgrind
$ valgrind ./exmaple
Memcheck is the default tool invoked
--leak-check=full: list details of each leak
--track-origins=yes: track the origin of
uninitialized values
others via valgrind --help
Buffer Overflow (Eg.1)

1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = calloc(
6 4, sizeof(int));
7 printf("%d\n", b[4]);
8 free(b);
9 return 0;
10 }
==31015== Invalid read of size 4
==31015== at 0x4005B0: main
(e1.c:7)
==31015== Address 0x51dc050 is 0
bytes after a block of
size 16 alloc'd
==31015== at 0x4C29860: calloc(in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==31015== by 0x4005A3: main
(e1.c:5)
Memory Leak (Eg.2)

1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = calloc(
6 4, sizeof(int));
7 printf("%d\n", b[3]);
8 return 0;
9 }
==32266== 16 bytes in 1 blocks are
definitely lost in loss
record 1 of 1
==32266== at 0x4C29860: calloc
(in /usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==32266== by 0x400553: main
(e2.c:5)
==32266== LEAK SUMMARY:
==32266== definitely lost: 16
bytes in 1 blocks
...
Dangling Pointer (Eg.3)
1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = calloc(
6 4, sizeof(int));
7 b[2] = 1;
8 free(b);
9 printf("%d\n", b[2]);
10 return 0;
11 }
==5021== Invalid read of size 4
==5021== at 0x4005CA: main
(e3.c:9)
==5021== Address 0x51dc048 is 8
bytes inside a block of
size 16 free'd
==5021== at 0x4C289DC: free (in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==5021== by 0x4005C1: main
(e3.c:8)
Double Free (Eg.4)
1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = malloc(
6 4 * sizeof(int));
7 b[2] = 1;
8 free(b);
9 free(b);
10 return 0;
11 }
==2819== Invalid free() / delete /
delete[] / realloc()
==2819== at 0x4C289DC: free (in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==2819== by 0x400578: main (e4.c:9)
==2819== Address 0x51dc040 is 0 bytes
inside a block of size 16
free'd
==2819== at 0x4C289DC: free (in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
Uninitialized Memory (Eg.5)
1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int ret;
6 int *b = malloc(
7 4 * sizeof(int));
8 ret = b[2];
9 free(b);
10 return ret;
11 }
==3911== Syscall param
exit_group(status) contains
uninitialised byte(s)
...
==3911== Uninitialised value was
created by a heap allocation
==3911== at 0x4C27730: malloc
(in /usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==3911== by 0x40054E: main
(e5.c:6)
Caveats
No bound checking on stack-allocated arrays
int main() {
int a[10];
a[11] = 42;
}
More time (20x-30x), more memory (2x)
Reveal problem only when input triggering it
is provided
Useful Links
Valgrind Quick Start Guide
http://valgrind.org/docs/manual/quick-start.
html#quick-start.intro
Valgrind Memcheck Manual
http://valgrind.org/docs/manual/mc-manual.html
Design and Architecture of Valgrind
Nicholas Nethercote & Julian Seward, Valgrind: A
Framework for Heavyweight Dynamic Binary
Instrumentation, PLDI07

You might also like