应用 Valgrind 定位 Linux 程序的内存问题

参考文章
Valgrind学习总结
应用 Valgrind 发现 Linux 程序的内存问题

Valgrind介绍

Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。Valgrind的体系结构如下图所示:

在这里插入图片描述

Valgrind包括如下一些工具:
  • Memcheck。这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。
  • Callgrind。它主要用来检查程序中函数调用过程中出现的问题。
  • Cachegrind。它主要用来检查程序中缓存使用出现的问题。
  • Helgrind。它主要用来检查多线程程序中出现的竞争问题。
  • Massif。它主要用来检查程序中堆栈使用中出现的问题。
  • Extension。可以利用core提供的功能,自己编写特定的内存调试工具。
Valgrind的使用
编译命令:
gcc hello.c -g -o hello

🐖 编译时加上-g选项可以定位到代码行
🐖 编译优化选项请选择O0,虽然这会降低程序的执行效率

调试命令:
valgrind -v --log-file=valgrind.log --tool=memcheck --leak-check=full --show-mismatched-frees=yes ./hello

说明:加--log-file=valgrind.log 会在当前目录下生成日志文件,日志不会在终端打印

检查内存错误:
valgrind --leak-check=full --show-reachable=yes --trace-children= yes   ./hello 

其中--leak-check=full指的是完全检查内存泄漏,--show-reachable=yes是显示内存泄漏的地点,--trace-children=yes是跟入子进程。
如果您的程序是会正常退出的程序,那么当程序退出的时候valgrind自然会输出内存泄漏的信息。
如果您的程序是个守护进程,那么也不要紧,我们 只要在别的终端下杀死memcheck进程(因为valgrind默认使用memcheck工具,就是默认参数—tools=memcheck):

killall memcheck 

这样我们的程序(./hello)就被kill了。

检查代码覆盖和性能瓶颈:

我们调用valgrind的工具执行程序:

valgrind --tool=callgrind ./sec_infod 

会在当前路径下生成callgrind.out.pid(当前生产的是callgrind.out.19689),如果我们想结束程序,可以:
#killall callgrind
然后我们看一下结果:
#callgrind_annotate --auto=yes callgrind.out.19689 >log
#vim log
callgrind_annotate可以把这个文件的内容转化成可读的形式。

一般像下面这样调用Valgrind:
频率较高的常用选项

1、要求用 memcheck这个工具对程序进行分析

 -–tool=[default: memcheck]
 -–tool=memcheck 

2、 将输出的信息写入到filename.PID 的文件里,PID是运行程序的进行ID

 –log-file=filename

3、指定就输出到 filename文件

 –log-file-exactly=filename

4、把输出信息发送到网络中指定的IP:PORT中 去

 –log-socket=IP:PORT

5、要求对leak给出详细信息

 –leak-ckeck=yes

6、完全检查内存泄漏

 –leak-check=full

7、如果为yes, valgrind会在每发现一个错误便停下让用户做选择是继续还是退出

 –gen-suppressions=[default: no]
用法: valgrind [options] prog-and-args [options]:

常用选项,适用于所有Valgrind工具

-tool=[default: memcheck] 最常用的选项。运行 valgrind中名为toolname的工具。默认memcheck。
h --help 显示帮助信息.
v –verbose 更详细的信息, 增加错误数统计。
-version 显示valgrind内核的版本,每个工具都有各自的版本。
q –quiet 安静地运行,只打印错误信息。
-trace-children=no|yes 跟踪子线程 [no]
-track-fds=no|yes 跟踪打开的文件描述[no]
-time-stamp=no|yes 增加时间戳到LOG信息 [no]
-log-fd= [number] 输出LOG到描述符文件 [2=stderr]
-log-file=[file] 将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID
-log-file-exactly=[file] 输出LOG信息到 file
-log-file-qualifier=[VAR] 取得环境变量的值来做为输出信息的文件名。 [none]
-log-socket=ipaddr:port 输出LOG到socket ,ipaddr:port

LOG信息输出

-xml=yes 将信息以xml格式输出,只有memcheck可用
--xml-file=mem.memcheck指定xml报告输出路径和名称
-num-callers=<number> show callers in stack traces [12]
定义在堆栈追踪过程中显示的最大嵌套调用数
-error-limit=no|yes 如果太多错误,则停止显示新错误 [yes]
-error-exitcode= 如果发现错误则返回错误代码 [0=disable]
-db-attach=no|yes 当出现错误,valgrind会自动启动调试器gdb。[no]
-db-command= 启动调试器的命令行选项[gdb -nw %f %p]

适用于Memcheck工具的相关选项:

-leak-check=no|summary|full [default: summary]
Leak是指,存在一块没有被引用的内存空间,或没有被释放的内存空间,如 summary,只反馈一些总结信息,告诉你有多少个malloc ,多少个free 等;如果是full 将输出所有的leaks,也就是定位到某一个malloc/free
-leak-resolution=low|med|high how much bt merging in leak check [default: low]
-show-reachable=[default: no] 如果为 no,只输出没有引用的内存leaks,或指向 malloc返回的内存块中部某处的leaks ;为yes,检测控制范围之外的泄漏,比如全局指针、static指针等
–undef-value-errors=[default: yes] 如果为 yes,memcheck将对无定义值错进行检查

valgrind报告解读

valgrind排查内存泄露

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值