valgrind调查内存leak

快有几个月没更新了,记录一下最近解决问题用到的工具吧.html

最近代码跑压力测试,老是发现内存在无规律的慢慢增长,所以在Android上用上了大名顶顶的valgrind,说实话,真是名不虚传,java

真是建议之后全部c/c++ 项目,无论有没有现象级的问题,用这个跑一下检测下一些隐藏得比较深的问题;linux

 

 

export G_SLICE=always-malloc c++

export G_DEBUG=gc-friendly 正则表达式

 

注:Android 4.4中跑valgrind ,把external中编译的valgrind拷贝到小程序

/data/valgrind目录,而后设置环境变量才能使用:多线程

export VALGRIND_LIB=/usbdisk/valgrind函数

 

 参考命令行:工具

valgrind -v --tool=memcheck  --track-fds=yes  --leak-check=full --show-reachable=yes --time-stamp=yes --undef-value-errors=no --malloc-fill=0xc --free-fill=0xd --freelist-vol=100000000 --trace-children=yes --num-callers=50  --suppressions=default.supp  --log-file=valgrind_gst ./cmdplayer -p gstreamer http://10.9.44.116/test.mp4

 

注:性能

Android 的external目录下有valgrind的源代码,mm 编译后拷贝到板子上就可使用valgrind了.

1,生成supp文件

         supp文件能够定义valgrind的检查过滤规则。若是你确实用过valgrind,你会发现其对内存的检查很是严厉,很容易存在误报(其实也不是误报,有时候那些错误只是你不关注的),尤为是对于libc中的malloc与free(好像还有new和delete,另外这个是个很tricky的地方,按照文档的意思是,libc里面malloc时,会额外分配一点内存用于某些事情来保证malloc的工做,而这些额外的内存不会被free释放掉,由于当线程释放的时候,linux内核会将这些额外的内存给释放了,从而内存检测工具的检查会被影响)以及一些其余的库(好比ACE?)。为了消除这些干扰信息,你须要生成supp文件。最简单的办法就是在启动valgrind的时候加上选项--gen-suppressions=all,再将生成的规则复制出来。固然,这不是一个聪明的办法。最好是将生成的结果整理一下,将多个类似的整理成一条。能够参考官方文档suppressing errors

    2,对程序的影响
        若是你编写的只是小型程序,你能够不关注这一部分。但若是是大型程序(尤为对性能有要求的)或者是多线程程序(大型程序应该都这样吧),你的程序会工做起来后有些不一样。第一,变的很是很是慢。valgrind模拟的一个软CPU,将可执行程序运行在其中。因此效率很低,速度慢不少,并且,valgrind的是单线程的(应该是),它会将你程序的全部线程统一管理起来,其实就是强制串行起来执行。因此你必定要明白这一点,用valgrind跑你的程序时,若是testcase挂掉了,看看是否是和性能有关的那些。
        另外,请注意,64位的valgrind,不能执行32位的程序。这一点我没有严格验证过,也多是版本没有更新的缘由,至少在我调试时,64位的rhel系统下,产品的64位的程序会建立2个32位的子进程,而后挂在那里,没有错误也没有警告。
    3,多进程追踪
        若是你只是一个单一的小程序,不用开子进程,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权限,则报告会没法生成。
  4,报告结果显示
   其实valgrind的报告结果是很详细的。可是不要认为那些开发team愿意去一条条阅读valgrind的内存错误结果报告。因此,图形化显示结果是很重要的。幸运的是,Jenkins中已经包含了valgrind插件,并且很是好用。
   安装valgrind插件:进入系统管理,插件管理中,在可选插件中搜索valgrind,而后安装便可。
   配置valgrind插件:插件的默认工做目录是Jenkins的工做目录,因此要显示结果须要将valgrind的报告结果复制入Jenkins的工做目录。这里须要的报告结果是xml格式的。Report Pattern:   设置检索报告的命名格式,通常生成的报告若是是%p_log.memcheck,那么这里就设置为*_log.memcheck.
  配置好以后,在配置的下方,会出现valgrind Results。当每次构建完成以后,点击进入后均可以看到当前内存错误数量的图表,以及每一个错误的函数名、函数调用关系等。
相关文章
相关标签/搜索