<HTML ><HEAD ><TITLE >A Closer View</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+ "><LINK REL="HOME" TITLE="Valgrind HOWTO" HREF="index.html"><LINK REL="PREVIOUS" TITLE="Getting it Installed" HREF="getinstalled.html"><LINK REL="NEXT" TITLE="Let's Go Deeper" HREF="deeper.html"></HEAD ><BODY CLASS="sect1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >Valgrind HOWTO</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="getinstalled.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="deeper.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="closerview">4. A Closer View</H1 ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="whyvalgrind">4.1. Why Valgrind?</H2 ><P > As said above, memory management is prone to errors that are too hard to detect. Common errors may be listed as: </P ><P > <P ></P ><OL TYPE="1" ><LI ><P >Use of uninitialized memory</P ></LI ><LI ><P >Reading/writing memory after it has been freed</P ></LI ><LI ><P >Reading/writing off the end of malloc'd blocks</P ></LI ><LI ><P >Reading/writing inappropriate areas on the stack</P ></LI ><LI ><P >Memory leaks -- where pointers to malloc'd blocks are lost forever</P ></LI ><LI ><P >Mismatched use of malloc/new/new[] vs free/delete/delete[]</P ></LI ><LI ><P >Some misuses of the POSIX pthreads API</P ></LI ></OL > </P ><P > These errors usually lead to crashes. </P ><P > This is a situation where we need Valgrind. Valgrind works directly with the executables, with no need to recompile, relink or modify the program to be checked. Valgrind decides whether the program should be modified to avoid memory leak, and also points out the spots of <SPAN CLASS="QUOTE" >"leak."</SPAN > </P ><P > Valgrind simulates every single instruction your program executes. For this reason, Valgrind finds errors not only in your application but also in all supporting dynamically-linked (.so-format) libraries, including the GNU C library, the X client libraries, Qt if you work with KDE, and so on. That often includes libraries, for example the GNU C library, which may contain memory access violations. </P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="usage">4.2. Usage</H2 ><DIV CLASS="sect3" ><H3 CLASS="sect3" ><A NAME="invoking">4.2.1. Invoking Valgrind</H3 ><P > The checking may be performed by simply placing the word <B CLASS="command" >valgrind</B > just before the normal command used to invoke the program. For example: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="screen" > #valgrind ps -ax </PRE ></FONT ></TD ></TR ></TABLE ><P > Valgrind provides thousands of options. We deliberately avoid them, not to make this article boring. </P ><P > The output contains the usual output of <B CLASS="command" >ps -ax</B > also with the detailed report by valgrind. Any error (memory related) is pointed out in the error report. </P ></DIV ><DIV CLASS="sect3" ><H3 CLASS="sect3" ><A NAME="erridentify">4.2.2. How to Identify the Error from the Error Report</H3 ><P > Consider the output of Valgrind for some test program: <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="screen" > ==1353== Invalid read of size 4 ==1353== at 0x80484F6: print (valg_eg.c:7) ==1353== by 0x8048561: main (valg_eg.c:16) ==1353== by 0x4026D177: __libc_start_main (../sysdeps/generic/libc-start.c :129) ==1353== by 0x80483F1: free@@GLIBC_2.0 (in /home/deepu/valg/a.out) ==1353== Address 0x40C9104C is 0 bytes after a block of size 40 alloc'd ==1353== at 0x40046824: malloc (vg_clientfuncs.c:100) ==1353== by 0x8048524: main (valg_eg.c:12) ==1353== by 0x4026D177: __libc_start_main (../sysdeps/generic/libc-start.c :129) ==1353== by 0x80483F1: free@@GLIBC_2.0 (in /home/deepu/valg/a.out) </PRE ></FONT ></TD ></TR ></TABLE > </P ><P > Here, 1353 is the process ID. This part of the error report says that a read error has occurred at line number 7, in the function <TT CLASS="function" >print</TT >. The function <TT CLASS="function" >print</TT > is called by function <TT CLASS="function" >main</TT >, and both are in the file <TT CLASS="filename" >valg_eg.c</TT >. The function <TT CLASS="function" >main</TT > is called by the function <TT CLASS="function" >__libc_start_main</TT > at line number 129, in <TT CLASS="filename" >../sysdeps/generic/libc-start.c</TT >. The function <TT CLASS="function" >__libc_start_main</TT > is called by <TT CLASS="function" >free@@GLIBC_2.0</TT > in the file <TT CLASS="filename" >/home/deepu/valg/a.out.</TT > Similarly details of calling <TT CLASS="function" >malloc</TT > are also given. </P ></DIV ><DIV CLASS="sect3" ><H3 CLASS="sect3" ><A NAME="errortypes">4.2.3. Types of Errors with Examples</H3 ><P > Valgrind can only really detect two types of errors: use of illegal address and use of undefined values. Nevertheless, this is enough to discover all sorts of memory management problems in a program. Some common errors are given below. </P ><DIV CLASS="sect4" ><H4 CLASS="sect4" ><A NAME="uninit-mem">4.2.3.1. Use of uninitialized memory</H4 ><P > Sources of uninitialized data are: </P ><P ></P ><UL ><LI ><P >local variables that have not been initialized.</P ></LI ><LI ><P >The contents of malloc'd blocks, before writing something there.</P ></LI ></UL ><P > This is not a problem with <TT CLASS="function" >calloc</TT > since it initializes each allocated bytes with 0. The <TT CLASS="function" >new</TT > operator in C++ is similar to <TT CLASS="function" >malloc</TT >. Fields of the created object will be uninitialized. </P ><P > Sample program: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" > #include <stdlib.h> int main() { int p, t; if (p == 5) /*Error occurs here*/ t = p+1; return 0; } </PRE ></FONT ></TD ></TR ></TABLE ><P > Here the value of <TT CLASS="literal" >p</TT > is uninitialized, therefore <TT CLASS="literal" >p</TT > may contain some random value (garbage), so an error may occur at the condition check. An uninitialized variable will cause error in 2 situations: </P ><P ></P ><UL ><LI ><P >When it is used to determine the outcome of a conditional branch. Eg:'if (p == 5)' in the above program.</P ></LI ><LI ><P >When it is used to generate a memory address. Eg: In the above program let there be an integer array a[10], and if you write 'a[p] = 1', it will generate an error.</P ></LI ></UL ></DIV ><DIV CLASS="sect4" ><H4 CLASS="sect4" ><A NAME="illegal-rw">4.2.3.2. Illegal read/write</H4 ><P > Illegal read/write errors occurs when you try to read/write from/to an address that is not in the address range of your program. </P ><P > Sample program: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" > #include <stdlib.h> int main() { int *p, i, a; p = malloc(10*sizeof(int)); p[11] = 1; /* invalid write error */ a = p[11]; /* invalid read error */ free(p); return 0; } </PRE ></FONT ></TD ></TR ></TABLE ><P > Here you are trying to read/write from/to address (p+sizeof(int)*11) which is not allocated to the program. </P ></DIV ><DIV CLASS="sect4" ><H4 CLASS="sect4" ><A NAME="invalid-free">4.2.3.3. Invalid free</H4 ><P > Valgrind keeps track of blocks allocated to your program with <TT CLASS="function" >malloc/new</TT >. So it can easily check whether argument to free/delete is valid or not. </P ><P > Sample program: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" > #include <stdlib.h> int main() { int *p, i; p = malloc(10*sizeof(int)); for(i = 0;i < 10;i++) p[i] = i; free(p); free(p); /* Error: p has already been freed */ return 0; } </PRE ></FONT ></TD ></TR ></TABLE ><P > Valgrind checks the address, which is given as argument to free. If it is an address that has already been freed you will be told that the free is invalid. </P ></DIV ><DIV CLASS="sect4" ><H4 CLASS="sect4" ><A NAME="mismatcheduse">4.2.3.4. Mismatched Use of Functions</H4 ><P > In C++ you can allocate and free memory using more than one function, but the following rules must be followed: </P ><P ></P ><UL ><LI ><P >If allocated with <TT CLASS="function" >malloc</TT >, <TT CLASS="function" >calloc</TT >, <TT CLASS="function" >realloc</TT >, <TT CLASS="function" >valloc</TT > or <TT CLASS="function" >memalign</TT >, you must deallocate with <TT CLASS="function" >free</TT >.</P ></LI ><LI ><P >If allocated with <TT CLASS="function" >new[]</TT >, you must deallocate with <TT CLASS="function" >delete[]</TT >.</P ></LI ><LI ><P >If allocated with <TT CLASS="function" >new</TT >, you must deallocate with <TT CLASS="function" >delete</TT >.</P ></LI ></UL ><P > Sample program: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" > #include <stdlib.h> int main() { int *p, i; p = ( int* ) malloc(10*sizeof(int)); for(i = 0;i < 10;i++) p[i] = i; delete(p); /* Error: function mismatch */ return 0; } </PRE ></FONT ></TD ></TR ></TABLE ><P > Output by valgrind is: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="screen" > ==1066== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) ==1066== malloc/free: in use at exit: 0 bytes in 0 blocks. ==1066== malloc/free: 1 allocs, 1 frees, 40 bytes allocated. ==1066== For a detailed leak analysis, rerun with: --leak-check=yes ==1066== For counts of detected errors, rerun with: -v </PRE ></FONT ></TD ></TR ></TABLE ><P > >From the above <SPAN CLASS="QUOTE" >"ERROR SUMMARY"</SPAN > it is clear that there is 0 bytes in 0 blocks in use at exit, which means that the malloc'd have been freed by <TT CLASS="function" >delete</TT >. Therefore this is not a problem in Linux, but this program may crash on some other platform. </P ></DIV ><DIV CLASS="sect4" ><H4 CLASS="sect4" ><A NAME="inv-sys-call-parm">4.2.3.5. Errors Occur Due to Invalid System Call Parameter</H4 ><P > Valgrind checks all parameters to system calls. </P ><P > Sample program: </P ><P > <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" > #include <stdlib.h> #include <unistd.h> int main() { int *p; p = malloc(10); read(0, p, 100); /* Error: unaddressable bytes */ free(p); return 0; } </PRE ></FONT ></TD ></TR ></TABLE > </P ><P > <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="screen" > ==1045== Syscall param read(buf) contains unaddressable byte(s) ==1045== at 0x4032AF44: __libc_read (in /lib/i686/libc-2.2.2.so) ==1045== by 0x4026D177: __libc_start_main (../sysdeps/generic/libc-start.c:129) ==1045== by 0x80483E1: read@@GLIBC_2.0 (in /home/deepu/valg/a.out) </PRE ></FONT ></TD ></TR ></TABLE > </P ><P > Here, <TT CLASS="literal" >buf = p</TT > contains the address of a 10 byte block. The <TT CLASS="function" >read</TT > system call tries to read 100 bytes from standard input and place it at <TT CLASS="literal" >p</TT >. But the bytes after the first 10 are unaddressable. </P ></DIV ><DIV CLASS="sect4" ><H4 CLASS="sect4" ><A NAME="memleak-detect">4.2.3.6. Memory Leak Detection</H4 ><P > Consider the following program: </P ><P > <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" > #include <stdlib.h> int main() { int *p, i; p = malloc(5*sizeof(int)); for(i = 0;i < 5;i++) p[i] = i; return 0; } </PRE ></FONT ></TD ></TR ></TABLE > </P ><P > <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="screen" > ==1048== LEAK SUMMARY: ==1048== definitely lost: 20 bytes in 1 blocks. ==1048== possibly lost: 0 bytes in 0 blocks. ==1048== still reachable: 0 bytes in 0 blocks. </PRE ></FONT ></TD ></TR ></TABLE > </P ><P > In the above program <TT CLASS="literal" >p</TT > contains the address of a 20-byte block. But it is not freed anywhere in the program. So the pointer to this 20 byte block is lost forever. This is known as memory leaking. We can get the leak summary by using the Valgrind option <TT CLASS="option" >--leak-check=yes</TT >. </P ></DIV ></DIV ><DIV CLASS="sect3" ><H3 CLASS="sect3" ><A NAME="error-suppress">4.2.4. How to Suppress Errors</H3 ><P > Valgrind detects numerous problems in many programs which come pre-installed on your GNU/Linux system. You can't easily fix these, but you don't want to see these errors (and yes, there are many!). So Valgrind reads a list of errors to suppress at startup, from a suppression file ending in <TT CLASS="filename" >.supp</TT >. </P ><P > Suppression files may be modified. This is useful if part of your project contains errors you can't or don't want to fix, yet you don't want to continuously be reminded of them. The format of the file is as follows. </P ><P > <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" > { Error name Type fun:function name, which contains the error to suppress fun:function name, which calls the function specified above } </PRE ></FONT ></TD ></TR ></TABLE > </P ><P > <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="screen" > Error name can be any name. type=ValueN, if the error is an uninitialized value error. =AddrN, if it is an address error.(N=sizeof(data type)) =Free, if it is a free error (eg:mismatched free) =Cond, if error is due to uninitialized CPU condition code. =Param, if it is an invalid system call parameter error. </PRE ></FONT ></TD ></TR ></TABLE > </P ><P > You can then run the program with: <TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="screen" > valgrind --suppressions=path/to/the/supp_file.supp testprog </PRE ></FONT ></TD ></TR ></TABLE > The output will not contain the errors specified in the suppression file. </P ></DIV ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="limitations-deps">4.3. Limitations and Dependencies of Valgrind.</H2 ><P > No software is free from limitations. The same is the case of Valgrind, however most programs work fine. The limitations are listed below. </P ><P ></P ><OL TYPE="1" ><LI ><P > Program runs 25 to 50 times slower.</P ></LI ><LI ><P >Increased memory consumption.</P ></LI ><LI ><P >Highly optimized code (compiled with -O1, -O2 options ) may sometimes cheat Valgrind.</P ></LI ><LI ><P >Valgrind relies on dynamic linking mechanism.</P ></LI ></OL ><P > Valgrind is closely tied to details of the CPU, operating system and to a less extent, compiler and basic C libraries. Presently Valgrind works only on the Linux platform (kernels 2.2.X or 2.4.X) on x86s. Glibc 2.1.X or 2.2.X is also required for Valgrind. </P ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="getinstalled.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="deeper.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Getting it Installed</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" > </TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Let's Go Deeper</TD ></TR ></TABLE ></DIV ></BODY ></HTML >