valgrind使用浅谈

1、Valgrind 简介

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具,它可在以下平台上运行: X86/Linux、AMD64/Linux、ARM/Linux、ARM64/Linux、PPC32/Linux、PPC64/Linux、PPC64LE/Linu   x、S390X/Linux、MIPS32/Linux、MIPS64/Linux、X86/Solaris , AMD64/Solaris, ARM/Android (2.3.x 及 更 高 版 本 ), ARM64/Android, X86/Android (4.0 及 更 高 版 本 ), MIPS32/Android, X86/FreeBSD, AMD64/FreeBSD, X86/Darwin 和 AMD64/Darwin (Mac OS X 10.12)

2、Valgrind 安装

下载地址:https://valgrind.org/downloads/current.html#current 解压后进入文件夹,执行

./configure --prefix=${install_path}

make -j16

make insatll

3、Valgrind 包含的工具

Memcheck

探测程序中内存管理存在的问题。它检查所有对内存的读/写操作,并截取所有的malloc/new/free/delete 调用。因此 memcheck 工具能够探测到以下问题:

  • 使用未初始化的内存
  • 读/写已经被释放的内存
  • 读/写内存越界
  • 读/写不恰当的内存栈空间
  • 内存泄漏
  • 使用 malloc/new/new[] 和 free/delete/delete[] 不匹配。
  • src 和 dst 的重叠

cachegrind

cachegrind 是一个 cache 剖析器。它模拟执行 CPU 中的 L1, D1 和 L2 cache,因此它能很精确的指出代码中的 cache 未命中。如果你需要,它可以打印出 cache 未命中的次数,内存引用和发生 cache 未命中的每一行代码,每一个函数,每一个模块和整个程序的摘要。如果你要求更细致的信息,它可以打印出每一行机器码的未命中次

数。在 x86 和 amd64 上,cachegrind 通过 CPUID 自动探测机器的 cache 配置,所以在多数情况下它不再需要更多的配置信息了。

helgrind

它主要用来检查多线程程序中出现的竞争问题。Helgrind    寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导  致难以发掘的错误。Helgrind 实现了名为”Eraser” 的竞争检测算法,并做了进一步改进,减少了报告错误的次数。

Callgrind

Callgrind 收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。在运行结束时,它会把分析数据写入一个文件。 callgrind_annotate 可以把这个文件的内容转化成可读的形式。

一般用法:

valgrind --tool=callgrind  ./sec_infod callgrind_annotate --auto=yes callgrind.out.[pid] > log vi log

Massif

堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈

的大小。Massif 能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。

lackey

lackey 是一个示例程序,以其为模版可以创建你自己的工具。在程序结束后,它打印出一些基本的关于程序执行统计数据。

4、Valgrind 参数

valgrind [options] prog-and-args [options]

常用选项

--tool=<name>

最常用的选项。运行 valgrind 中名为 toolname 的工具。默认memcheck。

-q --quiet

安静地运行,只打印错误信息。

--verbose

更详细的信息。

--trace-children=<yes|no>

跟踪子线程? [default: no]

--track-fds=<yes|no>

跟踪打开的文件描述? [default: no]

--time-stamp=<yes|no>

增加时间戳到 LOG 信息? [default: no]

--log-fd=<number>

输出 LOG 到描述符文件 [2=stderr]

--log-file=<file>

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

--log-file-exactly=<file>

输出 LOG 信息到 file,LOG 信息输出

--xml=yes

将信息以 xml 格式输出,只有 memcheck 可用

--db- command=<command>

启动调试器的命令行选项[gdb -nw %f %p]

-leak- check=<no|summary|full>

要求对 leak 给出详细信息? Leak 是指,存在一块没有被引用的内存空间,或没有被释放的内存空间,如 summary,只反馈一些总结信息,告诉你有多少个 malloc,多少个 free 等;如果是 full 将输出所有的 leaks,也就是定位到某一个 malloc/free,只有 memcheck 可用。

--show- reachable=<yes|no>

如果为 no,只输出没有引用的内存 leaks,或指向 malloc 返回的内存块中部某处的 leaks [default: no],只有 memcheck 可用。

更详细的参数指令见 https://phenix3443.github.io/notebook/software-engineering/debug/valgrind- practices.html#org9b75b1d

5、Valgrind 使用

  1. 编译程序时开启-g选项,如果没有调试信息,Valgrind无法定位异常代码位置。
  2. 如果待调试的是C++程序,考虑去掉函数内联调用(开启-fno-inline),这样可以更简单的查看 函数调用堆栈。或者,使用Valgrind选项–read-inline-info = yes可以读取内联函数的调试信

息,这样,即便程序使用了内联函数也能正确的显示调用堆栈信息。

关闭编译优化(-O)。在O1以上的优化级别下,memcheck工具会误报一些未初始化值的错 误。

  1. 使用-Wall编译代码,他能识别Valgrind在较高优化级别上可能会遗漏的部分。
  2. 如果程序是通过脚本启动的,可以修改脚本里启动程序的代码,或者使用 --trace- children=yes 选项来运行脚本。

常用内存检测命令

valgrind --log-file=./valgrind_report.log --leak-check=full --show-leak-kinds=all --show- reachable=no --track-origins=yes ./main

输出检测报告如图:

  • 左边显示类似行号的数字(10297)表示的是 Process ID。
  • 中间表示 valgrind 通过运行被测试程序,发现的内存问题。通过阅读这些信息,可以发现:
    • 这是一个对内存的非法读操作,非法写操作的内存是 8 bytes。
    • 发生错误时的函数堆栈,以及具体的源代码行号。
    • 非法读操作的具体地址空间。

valgrind输出结果会报告5种内存泄露,"definitely lost", "indirectly lost", "possibly lost", "still reachable", and "suppressed"。这五种内存泄露分析如下:

definitely lost

确认丢失,程序中存在内存泄露,应尽快修复。

当程序结束时如果一块动态分配的内存没有被释放且通过程序内的指针变量均无法 访问这块内存则会报这个错误。

indirectly lost

间接丢失。当使用了含有指针成员的类或结构时可能会报这个错误。这类错误无需直接修复,他们总是与"definitely lost"一起出现,只要修复"definitely lost"即可

possibly lost

可能丢失。大多数情况下应视为与"definitely lost"一样需要尽快修复,除非你的程序让一个指针指向一块动态分配的内存(但不是这块内存起始地址),然后通过运 算得到这块内存起始地址,再释放它。

当程序结束时如果一块动态分配的内存没有被释放且通过程序内的指针变量均无法 访问这块内存的起始地址,但可以访问其中的某一部分数据,则会报这个错误。

still reachable

可以访问,未丢失但也未释放。如果程序是正常结束的,那么它可能不会造成程序崩溃,但长时间运行有可能耗尽系统资源,因此笔者建议修复它。如果程序是崩溃

(如访问非法的地址而崩溃)而非正常结束的,则应当暂时忽略它,先修复导致程序崩溃的错误,然后重新检测。

suppressed

已被解决。出现了内存泄露但系统自动处理了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值