Valgrind
This is a short introduction on how to use Valgrind (memory checker)
What is it?
Valgrind is a program to check whether other programs are using their memory correctly or if there is memory corruption etc.
Valgrind is currently only available on Linux/x86, that means
logging in on salt or the machines in Ma416/Ma426, either locally at the computer or using ssh/PuTTY.
How to use it?
Example source code in C:
1. #include <stdlib.h>
2. #include <string.h>
3. #include <stdio.h>
4. int main(void) {
5. char *a, *b;
6. a = malloc(10);
7. b = malloc(30);
8. strcpy(b, "I am not a mushroom.");
9. strcpy(a, "This is not a blue cow.");
10. puts(a);
11. puts(b);
12. return 0;
13. }
This allocates 10 bytes of memory for a, then stores 20ish chars
at that location. This will obviously not fit, but that memory is stored
somewhere within the programs own memory and so does not cause a segmentation
fault due to invalid memory.
Compiling
Compiling the program with most warnings enabled (-Wall -W -pedantic), debug information (-g) and sending the result to 'testprog' (-o testprog):
lacolhost:/tmp> gcc -Wall -W -pedantic -g -o testprog testprog.c
lacolhost:/tmp>
(note that running gcc -wall -w ... instead of gcc -Wall -W ... will turn off all warnings instead, use capital W's)
Running the program
lacolhost:/tmp> ./testprog
This is not a blue cow.
ue cow.
.. not quite the result I wanted.
Running the program through valgrind
lacolhost:/tmp> valgrind ./testprog
==16413== Memcheck, a memory error detector.
==16413== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==16413== Using LibVEX rev 1658, a library for dynamic binary translation.
==16413== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==16413== Using valgrind-3.2.1-Debian, a dynamic binary instrumentation framework.
==16413== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==16413== For more details, rerun with: -v
==16413==
--16413-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--16413-- DWARF2 CFI reader: unhandled CFI instruction 0:50
==16413== Invalid write of size 4
==16413== at 0x80483E9: main (testprog.c:11)
==16413== Address 0x4174030 is 8 bytes inside a block of size 10 alloc'd
==16413== at 0x401D38B: malloc (vg_replace_malloc.c:149)
==16413== by 0x80483B2: main (testprog.c:7)
==16413==
==16413== Invalid read of size 1
==16413== at 0x401E211: strlen (mc_replace_strmem.c:246)
==16413== by 0x4098484: puts (in /lib/tls/libc-2.3.6.so)
==16413== by 0x80483F5: main (testprog.c:13)
==16413== Address 0x4174032 is 0 bytes after a block of size 10 alloc'd
==16413== at 0x401D38B: malloc (vg_replace_malloc.c:149)
==16413== by 0x80483B2: main (testprog.c:7)
==16413==
==16413== Invalid read of size 1
==16413== at 0x40A33B2: _IO_default_xsputn (in /lib/tls/libc-2.3.6.so)
==16413== by 0x40A08DB: _IO_file_xsputn (in /lib/tls/libc-2.3.6.so)
==16413== by 0x40984FE: puts (in /lib/tls/libc-2.3.6.so)
==16413== by 0x80483F5: main (testprog.c:13)
==16413== Address 0x4174032 is 0 bytes after a block of size 10 alloc'd
==16413== at 0x401D38B: malloc (vg_replace_malloc.c:149)
==16413== by 0x80483B2: main (testprog.c:7)
This is not a blue cow.
I am not a mushroom.
==16413==
==16413== ERROR SUMMARY: 31 errors from 3 contexts (suppressed: 11 from 1)
==16413== malloc/free: in use at exit: 40 bytes in 2 blocks.
==16413== malloc/free: 2 allocs, 0 frees, 40 bytes allocated.
==16413== For counts of detected errors, rerun with: -v
==16413== searching for pointers to 2 not-freed blocks.
==16413== checked 59,636 bytes.
==16413==
==16413== LEAK SUMMARY:
==16413== definitely lost: 40 bytes in 2 blocks.
==16413== possibly lost: 0 bytes in 0 blocks.
==16413== still reachable: 0 bytes in 0 blocks.
==16413== suppressed: 0 bytes in 0 blocks.
==16413== Use --leak-check=full to see details of leaked memory.
Here, we got the wanted result (blue cow and not a mushroom) because valgrind put out enough safety nets so our program did not corrupt itself.
This will print out when the program is doing something wrong, for instance
at testprog.c line 11 it is writing over memory allocated at
testprog.c line 7.
Showing leaked memory
Adding the flags --leak-check=full --show-reachable=yes will give additional information, like:
lacolhost:/tmp> valgrind --leak-check=full --show-reachable=yes ./testprog
...
==16351== 10 bytes in 1 blocks are definitely lost in loss record 1 of 2
==16351== at 0x401D38B: malloc (vg_replace_malloc.c:149)
==16351== by 0x80483B2: main (testprog.c:7)
==16351==
==16351==
==16351== 30 bytes in 1 blocks are definitely lost in loss record 2 of 2
==16351== at 0x401D38B: malloc (vg_replace_malloc.c:149)
==16351== by 0x80483C1: main (testprog.c:8)
Listing allocated memory that is never free()'d.
Fixing the program
Valgrind has shown that a did not get enough memory allocated and that a and b were never freed. New attempt at the code, increasing the size for a and freeing memory:
1. #include <stdlib.h>
2. #include <string.h>
3. #include <stdio.h>
4. int main(void) {
5. char *a, *b;
6. a = malloc(30);
7. b = malloc(30);
8. strcpy(b, "I am not a mushroom.");
9. strcpy(a, "This is not a blue cow.");
10. puts(a);
11. puts(b);
12. free(a);
13. free(b);
14. return 0;
15. }
Compiling and running
lacolhost:/tmp> gcc -Wall -W -pedantic -g -o testprog testprog.c
lacolhost:/tmp> ./testprog
This is not a blue cow.
I am not a mushroom.
lacolhost:/tmp> valgrind ./testprog
==17031== Memcheck, a memory error detector.
==17031== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==17031== Using LibVEX rev 1658, a library for dynamic binary translation.
==17031== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==17031== Using valgrind-3.2.1-Debian, a dynamic binary instrumentation framework.
==17031== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==17031== For more details, rerun with: -v
==17031==
--17031-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--17031-- DWARF2 CFI reader: unhandled CFI instruction 0:50
This is not a blue cow.
I am not a mushroom.
==17031==
==17031== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)
==17031== malloc/free: in use at exit: 0 bytes in 0 blocks.
==17031== malloc/free: 2 allocs, 2 frees, 60 bytes allocated.
==17031== For counts of detected errors, rerun with: -v
==17031== All heap blocks were freed -- no leaks are possible.
No errors and no leaks. Great!
Types of errors
What will Valgrind find?
- Allocated memory that is not freed ("definitely lost", "possibly lost", "still reachable")
- Trying to write into memory that was recently freed ("Invalid read", "Invalid write" and a stack trace where it was freed)
- Reading/writing outside an allocated array ("Invalid read", "Invalid write")
- Reading uninitialised memory ("Use of uninitialised value", "Conditional jump or move depends on uninitialised value")
- Files still open (memory not freed)
- etc..
What will Valgrind not find?
- Writing outside a static array (
char a[10] and writing >10 bytes there)
|