old-www/HOWTO/Valgrind-HOWTO/closerview.html

923 lines
16 KiB
HTML

<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
>&#13;As said above, memory management is prone to errors that are too
hard to detect. Common errors may be listed as:
</P
><P
>&#13;<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
>&#13;These errors usually lead to crashes.
</P
><P
>&#13;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
>&#13;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
>&#13;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"
>&#13;#valgrind ps -ax
</PRE
></FONT
></TD
></TR
></TABLE
><P
>&#13;Valgrind provides thousands of options. We deliberately avoid them, not
to make this article boring.
</P
><P
>&#13;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
>&#13;Consider the output of Valgrind for some test program:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; ==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
>&#13;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
>&#13;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
>&#13;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
>&#13;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
>&#13;Sample program:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="programlisting"
>&#13;#include &#60;stdlib.h&#62;
int main()
{
int p, t;
if (p == 5) /*Error occurs here*/
t = p+1;
return 0;
}
</PRE
></FONT
></TD
></TR
></TABLE
><P
>&#13;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
>&#13;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
>&#13;Sample program:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="programlisting"
>&#13;#include &#60;stdlib.h&#62;
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
>&#13;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
>&#13;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
>&#13;Sample program:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="programlisting"
>&#13;#include &#60;stdlib.h&#62;
int main()
{
int *p, i;
p = malloc(10*sizeof(int));
for(i = 0;i &#60; 10;i++)
p[i] = i;
free(p);
free(p); /* Error: p has already been freed */
return 0;
}
</PRE
></FONT
></TD
></TR
></TABLE
><P
>&#13;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
>&#13;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
>&#13;Sample program:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="programlisting"
>&#13;#include &#60;stdlib.h&#62;
int main()
{
int *p, i;
p = ( int* ) malloc(10*sizeof(int));
for(i = 0;i &#60; 10;i++)
p[i] = i;
delete(p); /* Error: function mismatch */
return 0;
}
</PRE
></FONT
></TD
></TR
></TABLE
><P
>&#13;Output by valgrind is:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; ==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
>&#13;&#62;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
>&#13;Valgrind checks all parameters to system calls.
</P
><P
>&#13;Sample program:
</P
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="programlisting"
>&#13;#include &#60;stdlib.h&#62;
#include &#60;unistd.h&#62;
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
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; ==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
>&#13;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
>&#13;Consider the following program:
</P
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="programlisting"
>&#13;#include &#60;stdlib.h&#62;
int main()
{
int *p, i;
p = malloc(5*sizeof(int));
for(i = 0;i &#60; 5;i++)
p[i] = i;
return 0;
}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; ==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
>&#13;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
>&#13;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
>&#13;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
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="programlisting"
>&#13;{
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
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;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
>&#13;You can then run the program with:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;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
>&#13;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
>&#13;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"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Let's Go Deeper</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>