Results 1 to 5 of 5

Thread: [Tutorial] Valgrind - Seek and Destroy Memory Leaks!

Threaded View

  1. #1

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    [Tutorial] Valgrind - Seek and Destroy Memory Leaks!

    Useful Debugging Techniques in Linux
    - by Wossname


    See Also:
    http://valgrind.org/docs/manual/manual.html (official Valgrind site)
    http://en.wikipedia.org/wiki/Valgrind (good Wikipedia pages)


    Synopsis:
    This tutorial introduces you to the Linux tool "Valgrind". Valgrind is a family of command-line
    tools that let you analyse the memory use of your C/C++ programs under Linux. Simply put, Valgrind
    tells you where you memory leaks appear and how bad they are. Armed with this information
    you can create memory-safe applications.


    Assumptions I made when writing this tutorial:
    - You know at least the basics of compiling simple C programs using GCC under Linux. I'll be covering these topics in future tutorials. Watch this space.
    - You've got valgrind and GCC installed on a Linux box.
    - You've got access to the console.
    - You've got user-permissions to both valgrind and GCC (they are not usually restricted anyway, you should be fine).



    -------------------

    Consider the following simple C program (simple.c)...

    Code:
    /* simple.c */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char** argv)
    {
    	char* bufferA = (char*)malloc(10);	/* LEAK ORIGINATES HERE */
    	
    	printf("Doing something useful...\n");
    		
    	/* We accidentally forget to free() that memory block! */				
    	return 0;   /* end successfully :) */
    }
    This is probably the most common way that memory leaks creep into a program: allocating a block of memory at the start of a program and forgetting to dispose of it at the end of the program.

    Compiling and running this program with
    gcc simple.c -o simple
    ./simple

    will give you the message: "Doing something useful" and then you'll end up back at the console
    prompt.

    Notice that the program doesn't crash, in fact nothing is really malfunctioning. But lets say one
    of your clients has noticed that your software is eating up memory and wants you to do something
    about it. This application could easily be 50,000 lines long and be extremely complex. So you
    need to identify the problem reliably and fast. Thus we turn to valgrind. Enter this command...

    valgrind simple

    This tells valgrind to analyse your application by running it in a controlled area of RAM and
    watching its behaviour extremely carefully. In our simple example valgrind displays the following
    information (the actual data will be different on your system but I'll highlight the salient
    points in red)...

    Quote Originally Posted by valgrind simple
    ==31699== Memcheck, a memory error detector for x86-linux.
    ==31699== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
    ==31699== Using valgrind-2.4.0, a program supervision framework for x86-linux.
    ==31699== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
    ==31699== For more details, rerun with: -v
    ==31699==
    Doing something useful...
    ==31699==
    ==31699== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
    ==31699== malloc/free: in use at exit: 10 bytes in 1 blocks.
    ==31699== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.
    ==31699== For counts of detected errors, rerun with: -v
    ==31699== searching for pointers to 1 not-freed blocks.
    ==31699== checked 49152 bytes.
    ==31699==
    ==31699== LEAK SUMMARY:
    ==31699== definitely lost: 10 bytes in 1 blocks.
    ==31699== possibly lost: 0 bytes in 0 blocks.
    ==31699== still reachable: 0 bytes in 0 blocks.
    ==31699== suppressed: 0 bytes in 0 blocks.
    ==31699== Use --leak-check=full to see details of leaked memory.
    This tells us that our program "simple" has 1 memory leak and it resulted in a loss of 10 bytes of RAM. That's all very well but it doesn't tell us where or how to fix it.

    So we need to specify a few more details to our compiler and to valgrind in order for it to reveal more info to us...

    Recompile the program with the -ggdb switch...
    gcc simple.c -o simple -ggdb
    (this inserts some debugging information into the resulting binary executable, valgrind can read this data).

    Then use valgrind again but with a new switch...
    valgrind --leak-check=full simple

    Now valgrind tell us (output truncated for brevity)...
    Quote Originally Posted by valgrind --leak-check=full simple
    ==31849== Memcheck, a memory error detector for x86-linux.
    ==31849== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
    ==31849== Using valgrind-2.4.0, a program supervision framework for x86-linux.
    ==31849== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
    ==31849== For more details, rerun with: -v
    ==31849==
    Doing something useful...
    ==31849==
    ==31849== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
    ==31849== malloc/free: in use at exit: 10 bytes in 1 blocks.
    ==31849== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.
    ==31849== For counts of detected errors, rerun with: -v
    ==31849== searching for pointers to 1 not-freed blocks.
    ==31849== checked 49152 bytes.
    ==31849==
    ==31849== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==31849== at 0x1B909222: malloc (vg_replace_malloc.c:130)
    ==31849== by 0x80483D5: main (simple.c:8)
    Now we have what we needed to know!
    by 0x80483D5: main (simple.c:8) tells us where the memory is being leaked from. Line 8 of simple.c is the line where we are using malloc() to create the buffer.

    We've just metaphorically saved ourselves hours of slavishly debugging 50,000 lines of 2-year-old code and it only took us 2 minutes! All we need to do now is fix this leak by adding the following lines...

    Code:
    /* simple.c */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char** argv)
    {
        char* bufferA = (char*)malloc(10);
    
        printf("Doing something useful...\n");
    
        /* We accidentally forgot to free() that memory block! */
    
        /* Bug now fixed by free()ing the block */
    
        free(bufferA);
        bufferA = NULL;
    
        return 0;   /* end successfully :) */
    }
    Recompile and then run valgrind on it again and ...

    Quote Originally Posted by
    gcc simple.c -o simple -ggdb
    valgrind --leak-check=full simple
    ==31896== Memcheck, a memory error detector for x86-linux.
    ==31896== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
    ==31896== Using valgrind-2.4.0, a program supervision framework for x86-linux.
    ==31896== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
    ==31896== For more details, rerun with: -v
    ==31896==
    Doing something useful...
    ==31896==
    ==31896== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
    ==31896== malloc/free: in use at exit: 0 bytes in 0 blocks.
    ==31896== malloc/free: 1 allocs, 1 frees, 10 bytes allocated.
    ==31896== For counts of detected errors, rerun with: -v
    ==31896== No malloc'd blocks -- no leaks are possible.
    This is the result we wanted! The highlighted line actually means "No malloc()s without correct free()s associated with them". Which means your memory leak has been fixed


    -------------


    Job done! Client happy. Time for the pub methinks.

    This has not even touched the surface of valgrind's full capabilities, its a very powerful tool. Go back to the top of this tutorial and check out the links to the website and the wiki.

    Wossy.
    Feel free to PM me

    (This tutorial is Copyright wossname (C) 2007)
    Last edited by wossname; Apr 4th, 2007 at 02:49 PM.
    I don't live here any more.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width