一、什么是valgrind
valgrind是一款运行在linux下的,用来定位c/c++程序中内存使用方面的错误的工具,包括:内存泄漏、使用未初始化的内存、读/写已释放的内存、读/写内存越界、使用malloc/new/new[]和free/delete/delete[]不匹配,等等。
Valgrind是帮助程序员寻找程序里的bug和改进程序性能的工具。程序通过valgrind运行时,valgrind收集各种有用的信息,通过这些信息可以找到程序中潜在的bug和性能瓶颈。
二、valgrind的安装
•下载
http://www.valgrind.org
下载最新版valgrind-3.3.1.tar.bz2
•安装
解压安装包:tar–jxvfvalgrind3.3.1.tar.bz2
解压后生成目录valgrind-3.3.1
cd valgrind-3.3.1
./configure
make
make install
好了,现在已经安装好了valgrind,可以开始了解如何使用它了。
三、valgrind的工具介绍
•使用Valgrind的工具包,你可以自动的检测许多内存管理和线程的bug,避免花费太多的时间在bug寻找上,使得你的程序更加稳固
•Valgrind支持很多工具:Memcheck,Addrcheck,Cachegrind,Massif,Helgrind和Callgrind等
•在运行Valgrind时,你必须指明想用的工具;
valgrind默认使用memcheck工具,即默认参数
--tools=memcheck
memcheck
这个工具可以用来寻找c、c++程序中内存管理的错误。写c或c++程序时,很多隐藏很深的bug是内存操作上出了问题,而这些在Memcheck面前都无处遁形。
Memcheck可以检查出下列几种内存操作上的错误:
•读写已经释放的内存
•读写内存块越界
•使用还未初始化的变量
•将无意义的参数传递给系统调用
•
内存泄漏
Cachegrind
•用于检查缓存使用的工具
•它模拟CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。
•在x86和amd64上,cachegrind通过CPUID自动探测机器的cache配置,所以在多数情况下它不再需要更多的配置信息了。
•cache对目前系统的性能有决定性的影响。因此这些信息可以指导程序员调整代码,最大限度的提高程序性能。
Callgrind
•Callgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。
•callgrind_annotate可以把这个文件的内容转化成可读的形式。
Helgrind
•用于检测多线程竞争资源的工具
•它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为”Eraser”的竞争检测算法,并做了进一步改进,减少了报告错误的次数。
Massif
•堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率
•程序开发者通过它可以深入了解程序的内存使用行为,从而对内存使用进行优化。这个功能对C++尤其有用(因为C++有很多隐藏的内存分配和释放)
四、Valgrind使用方法
•对被测程序的要求:
要求用gcc编译时使用-g选项
例如对test.c程序进行编译:gcc-g -o test test.c
•基本用法:
valgrind[option] exefilearg...
[option]:参数选项
exefile:可执行程序
arg...:程序参数
•使用内存检测:
option参数必须加上--leak-check=yes
举例:以程序test为例,检查test程序内存错误:
valgrind--leak-check=yes ./test
•详细参数说明见valgrind在线帮助手册 http://www.valgrind.org/docs/manual/mc-manual.html
五、Valgrind使用参数
5.1基本选项:这些选项对所有工具都有效
• -h --help
显示所有选项的帮助,包括内核和选定的工具两者。
• --help-debug
和--help相同,并且还能显示通常只有Valgrind的开发人员使用的调试选项。
• --version
显示Valgrind内核的版本号。工具可以有他们自已的版本号。这是一种保证工具只在它们可以运行的内核上工作的一种设置。这样可以减少在工具和内核之间版本兼容性导致奇怪问题的概率。
• -q --quiet
安静的运行,只打印错误信息。在进行回归测试或者有其它的自动化测试机制时会非常有用。
• -v--verbose
显示详细信息。在各个方面显示你的程序的额外信息,例如:共享对象加载,使用的重置,执行引擎和工具的进程,异常行为的警告信息。重复这个标记可以增加详细的级别。
•-d
调试Valgrind自身发出的信息。通常只有Valgrind开发人员对此感兴趣。重复这个标记可以产生更详细的输出。
•--tool=<toolname>[default: memcheck]
运行toolname指定的Valgrind,例如,Memcheck,Addrcheck,Cachegrind,等等。
•--trace-children=<yes|no>[default: no]
当这个选项打开时,Valgrind会跟踪到子进程中。这经常会导致困惑,而且通常不是你所期望的,所以默认这个选项是关闭的。
•--track-fds=<yes|no>[default: no]
当这个选项打开时,Valgrind会在退出时打印一个打开文件描述符的列表。每个文件描述符都会打印出一个文件是在哪里打开的栈回溯,和任何与文件描述符相关的详细信息比如文件名或socket信息。
•--time-stamp=<yes|no>[default: no]
当这个选项打开时,每条信息之前都有一个从程序开始消逝的时间,用天,小时,分钟,秒和毫秒表示。
•--log-fd=<number>[default: 2, stderr]
指定Valgrind把它所有的消息都输出到一个指定的文件描述符中去。默认值2, 是标准错误输出(stderr)。注意这可能会干扰到客户端自身对stderr的使用,Valgrind的输出与客户程序的输出将穿插在一起输出到stderr。
•--log-file=<filename>
指定Valgrind把它所有的信息输出到指定的文件中。实际上,被创建文件的文件名是由filename、‘.’和进程号连接起来的(即<filename>.<pid>),从而每个进程创建不同的文件。
• --log-file-exactly=<filename>
类似于--log-file,但是后缀“.pid”不会被添加。如果设置了这个选项,使用Valgrind跟踪多个进程,可能会得到一个乱七八糟的文件。
•--log-file-qualifier=<VAR>
当和--log-file一起使用时,日志文件名将通过环境变量$VAR来筛选,这对于MPI程序是有益的。
•--log-socket=<ip-address:port-number>
指定Valgrind输出所有的消息到指定的IP,指定的端口。当使用1500端口时,端口有可能被忽略。如果不能建立一个到指定端口的连接,Valgrind将输出写到标准错误(stderr)。这个选项经常和一个Valgrind监听程序一起使用。
5.2 错误相关选项:这些选项适用于所有产生错误的工具,比如Memcheck, 但是Cachegrind不行。
•--xml=<yes|no>[default: no]
当这个选项打开时,输出将是XML格式。只有Memcheck时生效。
•--xml-user-comment=<string>
在XML开头附加用户注释,仅在指定了--xml=yes时生效,否则忽略。
•--num-callers=<number>[default: 12]
默认情况下,Valgrind显示12层函数调用的函数名有助于确定程序的位置。可以通过这个选项来改变这个数字。这样有助在嵌套调用的层次很深时确定程序的位置。注意错误信息通常只回溯到最顶上的4个函数。(当前函数,和它的3个调用者的位置)。所以这并不影响报告的错误总数。最大值是50。注意高的设置会使Valgrind运行得慢,并且使用更多的内存,但是在嵌套调用层次比较高的程序中非常实用。
•--error-limit=<yes|no>[default: yes]
如果太多错误,则停止显示新错误
•--error-exitcode=<number>[default: 0]
指定如果Valgrind在运行过程中报告任何错误时的退出返回值,有两种情况;当设置为默认值(零)时,Valgrind返回的值将是它模拟运行的程序的返回值。当设置为非零值时,如果Valgrind发现任何错误时则返回这个值。
•--show-below-main=<yes|no>[default: no]
默认地,错误时的栈回溯不显示main()之下的任何函数。
•--suppressions=<filename>[default:$PREFIX/lib/valgrind/default.supp]
指定一个额外的文件读取不需要理会的错误;你可以根据需要使用任意多的额外文件。
•--gen-suppressions=<yes|no|all>[default: no]
当设置为yes时,Valgrind将会在每个错误显示之后自动暂停并且打印这一行:----Print suppression ? --- [Return/N/n/Y/y/C/c] ----
当设置为all时,Valgrind会对每一个错误打印一条禁止条目,而不向用户询问。
这个提示的行为和--db-attach选项(见下面)相同。这个选项对C++程序非常有用,它打印出编译器调整过的名字。
•--db-attach=<yes|no>[default: no]
当这个选项打开时,Valgrind将会在每次打印错误时暂停并打出一行:
---- Attach to debugger ? ---[Return/N/n/Y/y/C/c] ----
按下回车,或者N、回车,n、回车,Valgrind不会对这个错误启动调试器。按下Y、回车,或者y、回车,Valgrind会启动调试器并设定在程序运行的这个点。当调试结束时,退出,程序会继续运行。在调试器内部尝试继续运行程序,将不会生效。按下C、回车,或者c、回车,Valgrind不会启动一个调试器,并且不会再次询问。
注意:--db-attach=yes与--trace-children=yes有冲突。你不能同时使用它们。Valgrind在这种情况下不能启动。
•--db-command=<command>[default: gdb-nw%f %p]
通过--db-attach指定如何使用调试器。默认的调试器是gdb.%f会用可执行文件的文件名替换,%p会被可执行文件的进程ID替换。
•--input-fd=<number>[default: 0, stdin]
使用--db-attach=yes和--gen-suppressions=yes选项,在发现错误时,Valgrind会停下来去读取键盘输入。默认地,从标准输入读取,所以关闭了标准输入的程序会有问题。这个选项允许你指定一个文件描述符来替代标准输入读取。
•--max-stackframe=<number>[default: 2000000]
栈的最大值。如果栈指针的偏移超过这个数量,Valgrind则会认为程序是切换到了另外一个栈执行。
5.3 Valgrind可以识别的错误及错误提示
•malloc/free:in use at exit 内存在退出前没有被释放
•Invalidwrite of size 非法写内存:一般为数组越界
•Invalidread of size 非法读内存:一般为数组越界
•
definitelylost/possibly lost/still reachable in loss record内存未释放
•Invalidfree() / delete / delete[] 同一指针被多次释放
•Sourceand destination overlap 内存重叠(一般是使strncpy,memcpy引起)
•Syscallparamcontains uninitialisedbyte 调用系统函数时传入了未初始化的变量
•Conditionaljump or move depends on uninitialisedvalue 条件判断时使用了未初始化的变量
•Accessnot within mapped region/Stack overflow 栈溢出
•Mismatchedfree() / delete / delete [] new--delete malloc--free搭配错误
六、举例:valigrind在isearch3.2测试中的应用
•编译程序
被检测程序加入–g 编译选项保留调试信息(-g带可调试信息,让valgrind调试输出时指出相应信息的代码所在的行号)
• 内存泄露检测
valgrind--log-file=valgrind_log--leak-check=full --show-reachable=yes /opt/apache2/bin/httpd–X
valgrind--leak-check=full --show-reachable=yes --trace-children=yes ./iquery -f../conf/se.conf -s offer_gb?q=vcd –NT cache 0
其中参数:
--log-file=valgrind_log检测报告存入valgrind_log中
--leak-check=full 指的是完全检查内存泄漏
--show-reachable=yes是显示内存泄漏的地点
--trace-children=yes是跟入子进程
-NT 不输出时间统计信息
-cache N 指定cache的大小,取值范围[0,131072]
-X 启动单进程模式,即不会产生任何子进程
•阅读valgrind给出的内存泄露的报告
"LEAK SUMMARY":这表示下面是内存泄露的信息(造成内存丢失的程序行可以通过查看这一行前面的清单来定位)
"definitely lost":肯定丢失的部分,这种报告必须处理
“possiblylost”:可能丢失的部分,这是由于C/C++语言指针处理的特点造成的,这部分可能不太准确
完整ppt下载:http://download.csdn.net/search?sort=&q=valgrind&per_page=1