valgrind调试内存泄露
安装valgrind
源码方式,安装valgrind
下载最新的valgrind代码。源码下载地址见https://sourceware.org/ftp/valgrind/
# 下载
curl -O https://sourceware.org/ftp/valgrind/valgrind-3.16.0.tar.bz2
# 解压
tar xvf valgrind-3.16.0.tar.bz2
# 进入目录
cd valgrind-3.16.0/
# 自动生成编译脚本configure
./autogen.sh
如果出现如下错误:
running: aclocal
./autogen.sh: line 6: aclocal: command not found
error: while running 'aclocal'
缺少依赖,执行如下命令进行安装即可:
sudo apt-get install automake build-essential
安装完后再次执行./autogen.sh即可
./configure
make
sudo make install
Valgrind简单使用
现在来简单介绍下如何使用Valgrind来进行内存泄漏的检测。
进入到你被测程序的可执行文件所在路径,假设被测程序的可执行文件为xxx,那么执行如下命令即可启动Valgrind并同时启动被测试程序进行检测
valgrind --tool=memcheck --leak-check=full --error-limit=no --num-callers=50 --track-origins=yes --log-file=/home/aaron/valgrind_report.log ./xxxx
现在来简要介绍下上面命令的几个配置项的含义:
--tool=memcheck :使用内存检测的工具
--leak-check=full :有设置这个选项时,当被测程序结束时查找内存泄露。设置为summary,Valgrind会统计有多少内存泄露发生,若设置为full、yes,Valgrind会给出每一个独立的泄露的详细信息
--error-limit=no:如果错误太多要停止显示新的错误的选项
--num-callers=50:这个值默认是12,最高是50。表示显示多少层的堆栈,设置越高会使Valgrind运行越慢而且使用更多的内存,但是在嵌套调用层次比较高的程序中非常实用
--log-file=/home/aaron/valgrind_report.log: 指定检测结果报告的存放路径和文件名
./xxxx: 执行被测可执行文件
执行完上面的命令后就可以进行一些测试场景的执行,待要结束内存泄漏检测的时候在执行Valgrind命令的地方执行ctlr+c就可以终止Valgrind执行了,然后去查看指定路径产生的报告,报告会有类似如下的信息:
==18426== LEAK SUMMARY:
==18426== definitely lost: 0 bytes in 0 blocks
==18426== indirectly lost: 0 bytes in 0 blocks
==18426== possibly lost: 7,296 bytes in 12 blocks
==18426== still reachable: 112,897 bytes in 3,365 blocks
==18426== of which reachable via heuristic:
==18426== stdstring : 846 bytes in 22 blocks
==18426== suppressed: 0 bytes in 0 blocks
==18426== Reachable blocks (those to which a pointer was found) are not shown.
==18426== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==18426==
==18426== For counts of detected and suppressed errors, rerun with: -v
==18426== Use --track-origins=yes to see where uninitialised values come from
==18426== ERROR SUMMARY: 252 errors from 14 contexts (suppressed: 6 from 4)
重点关注 definitely lost(代表有确定的内存泄露)和indirectly lost(有间接的内存泄漏)
possibly lost表示可能有,这个可以根据实际情况让研发看下是否需要解决。
这几个的官方解释如下:
"definitely lost" means your program is leaking memory -- fix those leaks!
"indirectly lost" means your program is leaking memory in a pointer-based structure. (E.g. if the root node of a binary tree is "definitely lost", all the children will be "indirectly lost".) If you fix the "definitely lost" leaks, the "indirectly lost" leaks should go away.
"possibly lost" means your program is leaking memory, unless you're doing unusual things with pointers that could cause them to point into the middle of an allocated block; see the user manual for some possible causes. Use --show-possibly-lost=no if you don't want to see these reports.
"still reachable" means your program is probably ok -- it didn't free some memory it could have. This is quite common and often reasonable. Don't use --show-reachable=yes if you don't want to see these reports.
"suppressed" means that a leak error has been suppressed. There are some suppressions in the default suppression files. You can ignore suppressed errors.
调整被测程序的编译选项,显示内存错误的行号
被测程序出现内存错误时,程序需要配置编译选项,valgrind才可以正常显示错误出现的行号。
被测程序编译时,需以Debug模式进行编译。举例如下(cmake编译的程序):
cmake -DCMAKE_BUILD_TYPE=Debug ..
make