它模拟 CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中 cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数,这些可以看成程序的执行成本。以上数据其实对于app开发意义不大,仅作为参考。
转载请注明出处:http://blog.csdn.net/yf210yf/article/details/8023625
1、下载
http://valgrind.org/downloads/current.html
目前最新为valgrind 3.8.1 (tar.bz2) 版本
2、安装
标准gnu软件安装方式,./configure — make — make install
如果安装顺利,valgrind可执行程序已经被安装到/usr/bin下可以直接使用了
完整的说明:
1). Run ./configure, with some options if you wish. The only interesting
one is the usual --prefix=/where/you/want/it/installed.
2). Run "make".
3). Run "make install", possibly as root if the destination permissions
require that. --- Ubuntu下需要root权限,即应该这样运行: sudo make install
4). See if it works. Try "valgrind ls -l". Either this works, or it
bombs out with some complaint. In that case, please let us know
(see www.valgrind.org).
可能会出现以下的错误:
valgrind: Fatal error at startup: a function redirection
valgrind: which is mandatory
for
this platform-tool combination
valgrind: cannot be set up. Details of the redirection are:
valgrind:
valgrind: A must-be-redirected function
valgrind: whose name matches the pattern:
index
valgrind: in an object with soname matching: ld-linux.so.2
valgrind: was not found whilst processing
valgrind: symbols from the object with soname: ld-linux.so.2
valgrind:
valgrind: Possible fixes: (1, short term): install glibc's debuginfo
valgrind:
package
on this machine. (2, longer term): ask the packagers
valgrind:
for
your Linux distribution to please in future ship a non-
valgrind: stripped ld.so (or whatever the dynamic linker .so is called)
valgrind: that exports the above-named function using the standard
valgrind: calling conventions
for
this platform. The
package
you need
valgrind: to install
for
fix (1) is called
valgrind:
valgrind: On Debian, Ubuntu: libc6-dbg
valgrind: On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo
valgrind:
valgrind: Cannot
continue
-- exiting now. Sorry.
以上错误,是因为在Ubuntu下还需要一个LIB:libc6-dbg
运行:sudo apt-get install libc6-dbg 以安装libc6-dbg
然后再次运行: valgrind ls -l
转载请注明出处:http://blog.csdn.net/yf210yf/article/details/8023625
3、工具
valgrind包含几个标准的工具,它们是:
(1)memcheck
memcheck探测程序中内存管理存在的问题。它检查所有对内存的读/写操作,并截取所有的malloc/new/free/delete调用。因此memcheck工具能够探测到以下问题:
1)使用未初始化的内存
2)读/写已经被释放的内存
3)读/写内存越界
4)读/写不恰当的内存栈空间
5)内存泄漏
6)使用malloc/new/new[]和free/delete/delete[]不匹配。
(2)cachegrind
cachegrind是一个cache剖析器。它模拟执行CPU中的L1, D1和L2 cache,因此它能很精确的指出代码中的cache未命中。如果你需要,它可以打印出cache未命中的次数,内存引用和发生cache未命中的每一行代码,每一个函数,每一个模块和整个程序的摘要。如果你要求更细致的信息,它可以打印出每一行机器码的未命中次数。在x86和amd64上,cachegrind通过CPUID自动探测机器的cache配置,所以在多数情况下它不再需要更多的配置信息了。
(3)helgrind
helgrind查找多线程程序中的竞争数据。helgrind查找内存地址,那些被多于一条线程访问的内存地址,但是没有使用一致的锁就会被查出。这表示这些地址在多线程间访问的时候没有进行同步,很可能会引起很难查找的时序问题。
4、原理
valgrind对你的程序都做了些什么
valgrind被设计成非侵入式的,它直接工作于可执行文件上,因此在检查前不需要重新编译、连接和修改你的程序。要检查一个程序很简单,只需要执行下面的命令就可以了
valgrind --tool=tool_name program_name
比如我们要对ls -l命令做内存检查,只需要执行下面的命令就可以了
valgrind --tool=memcheck ls -l
不管是使用哪个工具,valgrind在开始之前总会先取得对你的程序的控制权,从可执行关联库里读取调试信息。然后在valgrind核心提供的虚拟CPU上运行程序,valgrind会根据选择的工具来处理代码,该工具会向代码中加入检测代码,并把这些代码作为最终代码返回给valgrind核心,最后valgrind核心运行这些代码。
如果要检查内存泄漏,只需要增加--leak-check=yes就可以了,命令如下
valgrind --tool=memcheck --leak-check=yes ls -l
不同工具间加入的代码变化非常的大。在每个作用域的末尾,memcheck加入代码检查每一片内存的访问和进行值计算,代码大小至少增加12倍,运行速度要比平时慢25到50倍。
valgrind模拟程序中的每一条指令执行,因此,检查工具和剖析工具不仅仅是对你的应用程序,还有对共享库,GNU C库,X的客户端库都起作用。
5、使用
首先,在编译程序的时候打开调试模式(gcc编译器的-g选项)。如果没有调试信息,即使最好的valgrind工具也将中能够猜测特定的代码是属于哪一个函数。打开调试选项进行编译后再用valgrind检查,valgrind将会给你的个详细的报告,比如哪一行代码出现了内存泄漏。
当检查的是C++程序的时候,还应该考虑另一个选项 -fno-inline。它使得函数调用链很清晰,这样可以减少你在浏览大型C++程序时的混乱。比如在使用这个选项的时候,用memcheck检查openoffice就很容易。当然,你可能不会做这项工作,但是使用这一选项使得valgrind生成更精确的错误报告和减少混乱。
一些编译优化选项(比如-O2或者更高的优化选项),可能会使得memcheck提交错误的未初始化报告,因此,为了使得valgrind的报告更精确,在编译的时候最好不要使用优化选项。
如果程序是通过脚本启动的,可以修改脚本里启动程序的代码,或者使用--trace-children=yes选项来运行脚本。
测试文件:
#include <iostream> #include <cstdlib> using namespace std; int main() { int *p1=new int; int *p2=new int; int *p3=(int*)malloc(sizeof(int)); int *p4=(int*)malloc(sizeof(int)); int *p5=new int; *p1=0; *p2=0; *p3=0; *p4=0; p5[10]=0; delete p1; free(p3); return 0; }
先编译
$ g++ -Wall -g main.cpp -o main
再用valgrind 测试
$ valgrind --tool=memcheck --leak-check=full ./main
得到
==13925== Memcheck, a memory error detector
==13925== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==13925== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==13925== Command: ./main
==13925==
==13925== Invalid write of size 4 /*数组越界错误*/
==13925== at 0x804864C: main (main.cpp:16)
==13925== Address 0x42f2130 is not stack'd, malloc'd or (recently) free'd
==13925==
==13925==
==13925== HEAP SUMMARY:
==13925== in use at exit: 12 bytes in 3 blocks
==13925== total heap usage: 5 allocs, 2 frees, 20 bytes allocated
==13925==
==13925== 4 bytes in 1 blocks are definitely lost in loss record 1 of 3
==13925== at 0x4029860: operator new(unsigned int) (vg_replace_malloc.c:292)
==13925== by 0x80485E8: main (main.cpp:7) /*new的内存未释放*/
==13925==
==13925== 4 bytes in 1 blocks are definitely lost in loss record 2 of 3
==13925== at 0x4029D56: malloc (vg_replace_malloc.c:270)
==13925== by 0x8048608: main (main.cpp:9) /*malloc的内存未释放*/
==13925==
==13925== 4 bytes in 1 blocks are definitely lost in loss record 3 of 3
==13925== at 0x4029860: operator new(unsigned int) (vg_replace_malloc.c:292)
==13925== by 0x8048618: main (main.cpp:10) /*new的内存未释放*/
==13925==
==13925== LEAK SUMMARY:
==13925== definitely lost: 12 bytes in 3 blocks
==13925== indirectly lost: 0 bytes in 0 blocks
==13925== possibly lost: 0 bytes in 0 blocks
==13925== still reachable: 0 bytes in 0 blocks
==13925== suppressed: 0 bytes in 0 blocks
==13925==
==13925== For counts of detected and suppressed errors, rerun with: -v
==13925== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 17 from 6)
测试效果不错!问题都检测出来了。
转载请注明出处:http://blog.csdn.net/yf210yf/article/details/8023625