Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C (http://www.go4expert.com/articles/c-tutorials/)
-   -   VALGRIND Memory Leak Detection Tutorial (http://www.go4expert.com/articles/valgrind-memory-leak-detection-tutorial-t26780/)

poornaMoksha 24Sep2011 21:21

VALGRIND Memory Leak Detection Tutorial
 
In a language like 'C', the programmer has almost complete control over memory operations but this brings in a problem that many of you might have faced : Memory errors. Although GDB can be used in many areas of these kind of problems but there are sometimes when programmer doesn't want to put too many breakpoints in the code. Also in a scenario where memory leak occurs, tool like GDB is of little help. So in situation like these a tool VALGRIND is extremely helpful. Lets discuss it today.

Valgrind works on executable files. Just simply run 'valgrind ./a.out' (of course with arguments needed by your program). Also make sure that you have turned off the optimizations for your program and use flag '-g' while compiling the code in order to see line numbers in output.

Examples



Lets understand the capability of Valgrind by focusing on various memory errors.

1) Lets consider a situation here:

Here is the code :

Code:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv){
  int k;
  int *p = malloc(sizeof(int) * 10);
  if (!p) return -1; /*malloc failed*/
  for (k = 0; k < 11; k++){
    a[k] = k; //here lies the problem for k = 10
  }
  free(p);
  return 0;
}

The problem with this code is that we are allocating memory eqvivalent to 10 integers but accessing 11th element thinking it as a part of allocated memory. Now when the above program is run, my compiler gives this kind of output :
Code:

*** glibc detected *** ./test_valgrind: free(): invalid next size (fast): 0x0000000001172010 ***
======= Backtrace: =========
/lib/libc.so.6(+0x775b6)[0x7fe4371cc5b6]
/lib/libc.so.6(cfree+0x73)[0x7fe4371d2e83]
./test_valgrind[0x4005c0]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7fe437173c4d]
./test_valgrind[0x4004a9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:05 1448916                            /home/himanshu/practice/test_valgrind
00600000-00601000 r--p 00000000 08:05 1448916                            /home/himanshu/practice/test_valgrind
00601000-00602000 rw-p 00001000 08:05 1448916                            /home/himanshu/practice/test_valgrind
01172000-01193000 rw-p 00000000 00:00 0                                  [heap]
7fe430000000-7fe430021000 rw-p 00000000 00:00 0
7fe430021000-7fe434000000 ---p 00000000 00:00 0
7fe436f3e000-7fe436f54000 r-xp 00000000 08:05 262224                    /lib/libgcc_s.so.1
7fe436f54000-7fe437153000 ---p 00016000 08:05 262224                    /lib/libgcc_s.so.1
7fe437153000-7fe437154000 r--p 00015000 08:05 262224                    /lib/libgcc_s.so.1
7fe437154000-7fe437155000 rw-p 00016000 08:05 262224                    /lib/libgcc_s.so.1
7fe437155000-7fe4372cf000 r-xp 00000000 08:05 265935                    /lib/libc-2.11.1.so
7fe4372cf000-7fe4374ce000 ---p 0017a000 08:05 265935                    /lib/libc-2.11.1.so
7fe4374ce000-7fe4374d2000 r--p 00179000 08:05 265935                    /lib/libc-2.11.1.so
7fe4374d2000-7fe4374d3000 rw-p 0017d000 08:05 265935                    /lib/libc-2.11.1.so
7fe4374d3000-7fe4374d8000 rw-p 00000000 00:00 0
7fe4374d8000-7fe4374f8000 r-xp 00000000 08:05 265932                    /lib/ld-2.11.1.so
7fe4376d5000-7fe4376d8000 rw-p 00000000 00:00 0
7fe4376f5000-7fe4376f7000 rw-p 00000000 00:00 0
7fe4376f7000-7fe4376f8000 r--p 0001f000 08:05 265932                    /lib/ld-2.11.1.so
7fe4376f8000-7fe4376f9000 rw-p 00020000 08:05 265932                    /lib/ld-2.11.1.so
7fe4376f9000-7fe4376fa000 rw-p 00000000 00:00 0
7fff22e72000-7fff22e87000 rw-p 00000000 00:00 0                          [stack]
7fff22fff000-7fff23000000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

This is bit difficult to decode especially for a newbie to understand what went wrong and where? Since its a small demo code so it could be easy to find out where the problem is but consider thousands of lines of code giving this type of run time error. In that situation using tool like valgrind is unavoidable.

Now, lets use valgrind, run the following command :

$ valgrind ./test_valgrind

and here is the output :
==6034== Memcheck, a memory error detector
==6034== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==6034== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==6034== Command: ./test_valgrind
==6034==
==6034== Invalid write of size 4
==6034== at 0x4005A8: main (valgrind.c:9)

==6034== Address 0x51b0068 is 0 bytes after a block of size 40 alloc'd
==6034== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==6034== by 0x40057C: main (valgrind.c:6)
==6034==
==6034==
==6034== FILE DESCRIPTORS: 3 open at exit.
==6034== Open file descriptor 2: /dev/pts/1
==6034== <inherited from parent>
==6034==
==6034== Open file descriptor 1: /dev/pts/1
==6034== <inherited from parent>
==6034==
==6034== Open file descriptor 0: /dev/pts/1
==6034== <inherited from parent>
==6034==
==6034==
==6034== HEAP SUMMARY:
==6034== in use at exit: 0 bytes in 0 blocks
==6034== total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==6034==
==6034== All heap blocks were freed -- no leaks are possible
==6034==
==6034== For counts of detected and suppressed errors, rerun with: -v
==6034== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
So as you can see the output, Valgrind tells the error that there was an 'Invalid write of size 4'. Also it tells the line number (see the line in bold above)

2) Lets consider another situation, here is the code :

Code:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv){
  int k;
  int *p = malloc(sizeof(int) * 10);
  if (!p) return -1; /*malloc failed*/
  for (k = 0; k < 10; k++){ // Read from k=0 to k=9
    p[k] = k;
  }

  for (k = 0; k < 11; k++){
      printf("\n p[%d] = [%d] \n",k,p[k]); // Problem is here when we try to read the array at index k = 10
  }
  free(p);
  return 0;
}

Here is the output without using valgrind :

p[0] = [0]

p[1] = [1]

p[2] = [2]

p[3] = [3]

p[4] = [4]

p[5] = [5]

p[6] = [6]

p[7] = [7]

p[8] = [8]

p[9] = [9]

p[10] = [135121]

but when we run the above code with valgrind we get the following output :
==6084== Memcheck, a memory error detector
==6084== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==6084== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==6084== Command: ./test_valgrind
==6084==

p[0] = [0]

p[1] = [1]

p[2] = [2]

p[3] = [3]

p[4] = [4]

p[5] = [5]

p[6] = [6]

p[7] = [7]

p[8] = [8]

p[9] = [9]
==6084== Invalid read of size 4
==6084== at 0x40061A: main (valgrind.c:13)

==6084== Address 0x51b0068 is 0 bytes after a block of size 40 alloc'd
==6084== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==6084== by 0x4005CC: main (valgrind.c:6)
==6084==

p[10] = [0]
==6084==
==6084== HEAP SUMMARY:
==6084== in use at exit: 0 bytes in 0 blocks
==6084== total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==6084==
==6084== All heap blocks were freed -- no leaks are possible
==6084==
==6084== For counts of detected and suppressed errors, rerun with: -v
==6084== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
So here we can see that valgrind easily tells that after reading the array at index '9' there is an invalid read of 4 bytes. It also tells the line number (see the line in bold above)

3) Lets try one more scenario, here is the code :

Code:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv){
  int k;
  int *p = malloc(sizeof(int) * 10);
  int *ptr = malloc(5); // Problem is here as this memory is not freed anywhere.
  if (!p) return -1; /*malloc failed*/
  for (k = 0; k < 10; k++){
    p[k] = k;
  }

  for (k = 0; k < 10; k++){
      printf("\n p[%d] = [%d] \n",k,p[k]);
  }
  free(p);
  return 0;
}

Now In above program a memory of 5 characters is allocated but is not free'd any where in the program.

When we run the program normally, programmer gets no clue that a memory was leaked. But when we run the above program with valgrind (use --leak-check=full flag this time), we get the following output :
==6167== Memcheck, a memory error detector
==6167== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==6167== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==6167== Command: ./test_valgrind
==6167==

p[0] = [0]

p[1] = [1]

p[2] = [2]

p[3] = [3]

p[4] = [4]

p[5] = [5]

p[6] = [6]

p[7] = [7]

p[8] = [8]

p[9] = [9]
==6167==
==6167== HEAP SUMMARY:
==6167== in use at exit: 5 bytes in 1 blocks
==6167== total heap usage: 2 allocs, 1 frees, 45 bytes allocated
==6167==
==6167== 5 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6167== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==6167== by 0x4005DA: main (valgrind.c:7)

==6167==
==6167== LEAK SUMMARY:
==6167== definitely lost: 5 bytes in 1 blocks
==6167== indirectly lost: 0 bytes in 0 blocks
==6167== possibly lost: 0 bytes in 0 blocks
==6167== still reachable: 0 bytes in 0 blocks
==6167== suppressed: 0 bytes in 0 blocks
==6167==
==6167== For counts of detected and suppressed errors, rerun with: -v
==6167== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
Here also, one can easily figure out that 5 bytes were not freed(see bold line in the output above) in the program and hence there was a memory leak.

Conclusion



I think the above three example help to present a strong conclusion that how useful is this tool for detecting run time memory related issues which otherwise are very difficult to find.

StarDrago 18Jan2012 01:38

Re: VALGRIND Memory Leak Detection Tutorial
 
I use deleaker - it's much more convenient for me....

Scripting 9Feb2012 22:00

Re: VALGRIND Memory Leak Detection Tutorial
 
valgrind is useful tool, good tutorial too!

StarDrago 9Feb2012 22:08

Re: VALGRIND Memory Leak Detection Tutorial
 
dn't dispute with me:cuss: :crazy: . I'm nice! :D

Scripting 9Feb2012 22:23

Re: VALGRIND Memory Leak Detection Tutorial
 
Quote:

Originally Posted by StarDrago (Post 92164)
dn't dispute with me:cuss: :crazy: . I'm nice! :D

Yea, dealeaker is good too :wacky: Cheerz! :D

StarDrago 10Feb2012 21:27

Re: VALGRIND Memory Leak Detection Tutorial
 
Quote:

Originally Posted by Scripting (Post 92165)
Yea, dealeaker is good too :wacky: Cheerz! :D

It's true :pleased:

StarDrago 21Feb2012 00:01

Re: VALGRIND Memory Leak Detection Tutorial
 
Does anybody among me use it tool? :pleased:

MasterAvalons 15May2012 01:34

Re: VALGRIND Memory Leak Detection Tutorial
 
Yes, of course. :pleased:


All times are GMT +5.5. The time now is 18:23.