Linux 下几款程序内存泄漏检查工具

 2023-09-05 阅读 214 评论 0

摘要:Linux 下几款程序内存泄漏检查工具 chenyoubing | 发布于 2016-07-23 10:08:09 | 阅读量 93 | 无 写这篇博客的原因呢是因为自己在编写基于Nginx磁盘缓存管理程序,目前已经进入测试阶段,关于这个程序的测试分为几个主要步骤: 1.内存管理是否正确(因为这个

Linux 下几款程序内存泄漏检查工具
chenyoubing | 发布于 2016-07-23 10:08:09 | 阅读量 93 | 无
写这篇博客的原因呢是因为自己在编写基于Nginx磁盘缓存管理程序,目前已经进入测试阶段,关于这个程序的测试分为几个主要步骤:
1.内存管理是否正确(因为这个程序本身开辟很多内存空间进行缓存管理,同时这个程序程序本身就是基于C/C++开发的,内存管理机制一直是程序员头痛的东西)
2.程序的健硕性如何(服务器任何程序的基本要求就是要满足高并发的要求,也就是说,如果达不到这个基本要求,程序并并不能成为服务器)
针对第一点,以下将介绍几款内存泄漏检查工具
工具 描述
valgrind 一个强大开源的程序检测工具
mtrace GNU扩展,用来跟踪malloc,mtrace为内存分配函数(malloc,rellaoc,memalign,free)安装hook函数
dmalloc 用于检查C/C++内存泄漏的工具,即是检查是否存在程序运行结束还没有释放的内存,以一个运行库发布
memwatch 和dmalloc一样,它能检测未释放的内存、同一段内存被释放多次、位址存取错误及不当使用未分配之内存区域
mpatrol 一个跨平台的 C++ 内存泄漏检测器
dbgmem 也是一个动态库发布的形式,优点类似dmalloc,但是相比之下,可能特点少了一些
Electric Fence 不仅仅能够跟踪malloc()和free(),同时能够检查读访问以及写入,能够准确指出导致错误的指令
Valgrind详解
valgrind

Valgrind包括以下一些工具:

1.Memcheck:这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够给发现开发中绝大多数的内存错误使用的情况,比如:使用未初始化
2.callgrind:它主要用来检查程序中函数中调用过程中出现的问题
3.cachegrind:它主要用来检查程序中缓存使用出现的问题
4.Helgrind:它主要用来检查多线程中出现的竞争问题
5.Massif:它主要用来检查程序中堆栈使用中出现的问题
6.Extension:可以使用core提供的 功能,自己编写特定的内存调试 工具
Linux程序内存空间布局
memory_distribution

代码段(.text):这里存放的是CPU要执行的指令,代码是可共享的,相同的代码在内存中只有一份拷贝,同时这个段是只读的,防止程序由于错误而修改自身指令
初始化数据段(.data)。这里存放的是程序中需要明确赋初始值的变量,例如位于所有函数之外的全局变量:int val=100。需要强调的是,以上两段都是位于程序的可执行文件中,内核在调用exec函数启动该程序时从源程序文件中读入。
未初始化数据段(.bss)。位于这一段中的数据,内核在执行该程序前,将其初始化为0或者null。例如出现在任何函数之外的全局变量:int sum;以及未初始化或初值为0的全局变量和静态局部变量
堆(Heap)。这个段用于在程序中进行动态内存申请,例如经常用到的malloc,new系列函数就是从这个段中申请内存。
已初始化且初值非0的全局变量和静态局部变量
栈(Stack)。函数中的局部变量以及在函数调用过程中产生的临时变量都保存在此段中。可执行代码、字符串字面值、只读变量。
内存检查原理
Memcheck检测内存问题的原理图:

memory_check

1.Valid-value表:

对于进程的整个地址空间中的每一字节(byte),都有与之对应的8个bits,对于CPU的每个寄存器,也有一个与之对应的bit向量。这些bits负责记录该字节或者寄存器值是否具有有效 的、已经初始化的值

2.Valid-Address表

对于进程整个地址空间中的 么一个字节(byte),还有与 之对应的1bit,负责记录该地址是否能够被读写。

检测原理

当要读写内存中的某个字节时,首先检查这个字节对应的A bit。如果该A bit显示该位置是无效位置,memcheck则报告读写错误。
内核(core)类似于 一个虚拟的CPU的环境,这样当内存中的某个字节被加载到真实的CPU中时,该字节对应的V bit也被加载到虚拟的CPU环境中,一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序 的输出,则memcheck会检查对应的vbits,如果该值尚未初始化,则会报告使用未初始化内存错误。
接下来我主要是介绍valgrind的安装和使用,关于其他的工具,大家可以自己上网去查阅资料,谢谢配合!
Valgrind 安装
1.解压安装包
tar -jxvf valgrind-3.11.0.tar.bz2 -C /usr/local/src
2.进入目录安装
cd /usr/local/src/valgrind-3.11.0
3.运行./autogen.sh 设置环境(需要标准的autoconf工具)
./autogen.sh
4.配置Valgrind,生成MakeFile文件
./configure --prefix=/usr/local
5.编译和安装valgrind
make && make install
valgrind 使用
第一步:准备好程序

为了valgrind发现的错误更精确,如能够定位到源代码的行,建议在编译时加上-g参数,编译优化选项选择O0(不要优化)
第二步:在valgrind下,运行可执行程序

利用valgrind调试内存问题,不需要重新编译源程序,它的输入就是二进制的可执行程序。调用Valgrind的通用格式是:valgrind [valgrind-options] your-prog [your-prog-options]
Valgrind 的参数分为两类,一类是 core 的参数,它对所有的工具都适用;另外一类就是具体某个工具如 memcheck 的参数。Valgrind 默认的工具就是 memcheck,也可以通过“–tool=tool name”指定其他的工具。Valgrind 提供了大量的参数满足你特定的调试需求,具体可参考其用户手册。
valgrind
momery_dector

利用Memcheck发现常见的内存问题总结
Memcheck将内存泄露分为两种,一种是可能的内存泄露(Possibly lost),另外一种是确定的内存泄露(Definitely lost)。Possibly lost 是指仍然存在某个指针能够访问某块内存,但该指针指向的已经不是该内存首地址。Definitely lost 是指已经不能够访问这块内存。而Definitely lost又分为两种:直接的(direct)和间接的(indirect)。直接和间接的区别就是,直接是没有任何指针指向该内存,间接是指指向该内存的指针都位于内存泄露处。在上述的例子中,根节点是directly lost,而其他节点是indirectly lost

Valgrind常用的命令
内存泄漏检查

valgrind --leak-check=full --show-reachable=yes --trace-children= yes [your program] > logfile /logfile加上会好些,程序在执行期间stderr会有一些输出。提示比较多/
其中–leak-check=full 指的是完全检查内存泄漏,–show-reachable=yes是显示内存泄漏的地点,–trace-children=yes是跟入子进程。 –log-file=”log.xml”输出到XML文件

如果您的程序是会正常退出的程序,那么当程序退出的时候valgrind自然会输出内存泄漏的信息。如果您的程序是个守护进程,那么也不要紧,我们 只要在别的终端下杀死memcheck进程(因为valgrind默认使用memcheck工具,就是默认参数—tools=memcheck):
killall memcheck
这样我们的程序(./a.out)就被kill了。

检查代码覆盖和性能瓶颈

我们调用valgrind的工具执行程序
valgrind --tool=callgrind [program]
会在当前路径下生成callgrind.out.pid(当前生产的是callgrind.out.19689),如果我们想结束程序,可以:

killall callgrind
然后我们看一下结果:

callgrind_annotate --auto=yes callgrind.out.19689 >log
使用callgrind工具生成性能分析数据

最基本使用

valgrind --tool=callgrind [program]
如果你调试的程序是多线程,你也可以在命令行中加一个参数 –separate-threads=yes。这样就会为每个线程单独生成一个性能分析文件

valgrind --tool=callgrind --separate-threads=yes [program]
把callgrind生成的性能数据转换成dot格式数据

脚本下载地址

python gprof2dot.py -f callgrind -n10 -s callgrind.out.31113 > valgrind.dot
把dot数据转换成图片格式

dot -Tpng valgrind.dot -o valgrind.png
使用Valgrind和ThreadSanitizer检测多线程错误

Valgrind一般用做内存泄露和访存越界检测,除此之外,其实它也支持对data race及一些简单的多线程问题的检查。Valgrind工具集里面,helgrind和drd都能用来完成这种检测。你可以用valgrind –tool=helgrind或valgrind –tool=drd来启用它。只要应用使用的线程模型是POSIX thread(pthread),这两个工具就能进行检测。这两个工具间差别不大,下面我就基于helgrind来介绍下用法:
hegrind 主要用来检查下面的错误:
资源不安全访问
死锁问题
POSIX pthreads API的错误使用
valgrind --tool=helgrind --log-file=helgrind.log [program]

转载于:https://www.cnblogs.com/Dennis-mi/articles/6599526.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/785.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息