本文在学习过程中简单摘抄,如果冒犯,请谅解!
一、介绍
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查找内存地址,那些被多于一条线程访问的内存地址,但是没有使用一致的锁就会被查出。这表示这些地址在多线程间访问的时候没有进行同步,很可能会引起很难查找的时序问题。
二、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的客户端库都起作用。
三、调试
在编译程序的时候打开调试模式(gcc编译器的-g选项)。如果没有调试信息,即使最好的valgrind工具也将很难猜测特定的代码是属于哪一个函数。打开调试选项进行编译后再用valgrind检查,valgrind将会给你的个详细的报告,比如哪一行代码出现了内存泄漏。
==4187== To see them, rerun with: –show-reachable=yes
这里的“4187”指的是执行ls -l的进程ID,这有利于区别不同进程的报告。memcheck会给出报告,分配置和释放了多少内存,有多少内存泄漏了,还有多少内存的访问是可达的,检查了多少字节的内存。
许多有用的工具被作为标准而提供。
多进程追踪:
如果你只是一个单一的小程序,不用开子进程,valgrind挺好用的。如果你要用valgrind去追踪多进程程序中的内存泄露,就有点繁琐了。有几个选项要特别注意。
--trace-children=yes
这个是必须的,打开追踪子进程
--log-file=<filename> --xml-file=<filename>
文本格式报告和xml格式报告的报告名称,推荐使用%p_log.memcheck
之类的名字,%p
会被valgrind转义成进程号,这样每一个进程都拥有一份独立的报告。
--child-silent-after-fork=yes
这个看情况,如果不打开的话,报告会更详细,错误定位可能会更精准,但是多份报告会混杂在一起,会直接破坏xml格式的报告
--trace-children-skip=patt1,patt2,... --trace-children-skip-by-arg=patt1,patt2,...
如果不使用这个,valgrind会追踪所有子进程,哪怕这个进程是java的。所以对应的,你需要让valgrind过滤一些子进程,--trace-children-skip
是根据exec的file/path中的字符串匹配来过滤,--trace-children-skip-by-arg
是根据exec的argv参数来过滤。没有正则表达式,只有*,?匹配两个符号可用。
另外,对于被执行程序而言,valgrind是other权限组的,所以记得更改执行权限。然后valgrind的报告会生成在,启动valgrind时用户所在的目录处。子进程的报告会生成在子进程程序所在目录。例如如果java在/bin/下,这报告会生成在/bin/里。但如果valgrind没有su权限,则报告会无法生成。
Valgrind官方网站