24 August 2002
Revision History | ||
---|---|---|
Revision 1.1 | 2002-09-15 | Revised by: tab |
Converted to XML 4.1.2, added gfdl, reviewed, author revisions | ||
Revision 1.0 | 2002-08-24 | Revised by: SS |
Initial release |
Valgrind is an open-source tool for finding memory-management problems in Linux-x86 executables. It detects memory leaks/corruption in the program being run. It is being developed by Julian Seward.
Copyright (C)2002 Deepak P, Sandeep S.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in Appendix A entitled "GNU Free Documentation License".
Kindly forward feedback and criticism to Deepak.P or/and Sandeep.S. We shall be indebted to anybody who points out errors and inaccuracies in this document; we will rectify them as soon as we are informed.
Uncompress, compile and install it:
#tar xvfz valgrind-1.0.0.tar.gz #cd valgrind-1.0.0 #./configure #make #make install |
Add the path to your path variable. Now valgrind is ready to catch the bugs.
These errors usually lead to crashes.
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 "leak."
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.
#valgrind ps -ax |
Valgrind provides thousands of options. We deliberately avoid them, not to make this article boring.
Consider the output of Valgrind for some test program:
==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) |
Sources of uninitialized data are:
#include <stdlib.h> int main() { int p, t; if (p == 5) /*Error occurs here*/ t = p+1; return 0; } |
#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; } |
#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; } |
#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; } |
==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 |
Valgrind checks all parameters to system calls.
#include <stdlib.h> #include <unistd.h> int main() { int *p; p = malloc(10); read(0, p, 100); /* Error: unaddressable bytes */ free(p); return 0; } |
==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) |
Consider the following program:
#include <stdlib.h> int main() { int *p, i; p = malloc(5*sizeof(int)); for(i = 0;i < 5;i++) p[i] = i; return 0; } |
==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. |
{ Error name Type fun:function name, which contains the error to suppress fun:function name, which calls the function specified above } |
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. |
You can then run the program with:
valgrind --suppressions=path/to/the/supp_file.supp testprog |
#include <stdlib.h> int main() { int *p, *a; p = malloc(10*sizeof(int)); a = malloc(10*sizeof(int)); a[3] = p[3]; free(a); free(p); return 0; } /* produce no errors */ |
#include <stdlib.h> int main() { float *p, *a; p = malloc(10*sizeof(float)); a = malloc(10*sizeof(float)); a[3] = p[3]; free(a); free(p); return 0; } /* produces error */ |
Have a look on the following program. Run it.
#include <stdlib.h> int main() { int *p, j; p = malloc(5*sizeof(int)); j = p[5]; if (p[5] == 1) i = p[5]+1; free(p); return 0; } |
==7436== I1 refs: 12,841 ==7436== I1 misses: 238 ==7436== L2i misses: 237 ==7436== I1 miss rate: 1.85% ==7436== L2i miss rate: 1.84% ==7436== ==7436== D refs: 5,914 (4,626 rd + 1,288 wr) ==7436== D1 misses: 357 ( 324 rd + 33 wr) ==7436== L2d misses: 352 ( 319 rd + 33 wr) ==7436== D1 miss rate: 6.0% ( 7.0% + 2.5% ) ==7436== L2d miss rate: 5.9% ( 6.8% + 2.5% ) ==7436== ==7436== L2 refs: 595 ( 562 rd + 33 wr) ==7436== L2 misses: 589 ( 556 rd + 33 wr) ==7436== L2 miss rate: 3.1% ( 3.1% + 2.5% ) |
L2i misses means the number of instruction misses that occur in L2 cache. L2d misses means the number of data misses that occur in L2 cache. Total number of data references = Number of reads + Number of writes. Miss rate means fraction of misses that are not found in the upper level. |
I1 cache: 16384 B, 32 B, 4-way associative D1 cache: 16384 B, 32 B, 4-way associative L2 cache: 262144 B, 32 B, 8-way associative Command: ./a.out Events recorded: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw Events shown: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw Event sort order: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw Thresholds: 99 0 0 0 0 0 0 0 0 Include dirs: User annotated: valg_flo.c Auto-annotation: off |
User-annotated source: valg_flo.c:
Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw . . . . . . . . . #include<stdlib.h> . . . . . . . . . int main() 3 1 1 . . . 1 0 0 { . . . . . . . . . float *p, *a; 6 1 1 . . . 3 0 0 p = malloc(10*sizeof(float)); 6 0 0 . . . 3 0 0 a = malloc(10*sizeof(float)); 6 1 1 3 1 1 1 1 1 a[3] = p[3]; 4 0 0 1 0 0 1 0 0 free(a); 4 0 0 1 0 0 1 0 0 free(p); 2 0 0 2 0 0 . . . } |
If you have found any glaring typos, or outdated info in this document, please let us know.
Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.
Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in the section entitled "GNU Free Documentation License".
If you have no Invariant Sections, write "with no Invariant Sections" instead of saying which ones are invariant. If you have no Front-Cover Texts, write "no Front-Cover Texts" instead of "Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.