[Support]
Home
Computer Laboratories
Q&A database
Computer systems
    Backup
    Computer Lab Bookings
    Computer Laboratories
    Disk storage
    Equipment for loan
    Machine status
    Network
    Printing
    Servers
    Software
        Usage
        Windows
    Statistics
    Sun Ray terminals
    User accounts
    Web pages
E-mail
Policies and procedures
Contact us
Staff
News and system status

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)

Questions or problems?
Send mail to:

support@cs.umu.se