Valgrind Memcheck

6 篇文章 0 订阅
1 篇文章 0 订阅

Valgrind Memcheck

一、Valgrind Memcheck

有关 Memcheck 和其他工具的完整文档,请阅读《用户手册》,这里知识简单介绍如何基础的使用Memcheck。

二、准备

编译程序时使用-g选项,这样Memcheck的错误信息就能包含准确的行号。
如果你觉得编译速度没关系的话,使用-Oo选项也是好的。
使用 -O1 时,错误信息中的行号可能会不准确,不过一般来说,在以 -O1 编译的代码上运行 Memcheck 时效果相当不错,与运行 -O0 时相比,速度提升相当显著。不建议使用 -O2 或更高版本,因为 Memcheck 有时会报告实际上并不存在的未初始化值错误。

三、在Memcheck下运行你的程序

比如,像这样程序运行:

myprog arg1 arg2

使用如下命令就可以检查你的程序内存泄漏问题

valgrind --leak-check=yes myprog arg1 arg2

Memcheck 是默认工具。使用 --leak-check 选项可打开详细的内存泄漏检测器。

你的程序运行速度会比正常情况下慢很多(例如 20 到 30 倍),而且会占用更多内存。Memcheck 会就其检测到的内存错误和泄露信息发出来

四、解读Memcheck的输出结果

下面是一个C程序,文件为test.c, 其中存在内存错误和内存泄漏

  #include <stdlib.h>
  void f(void)
  {
     int* x = malloc(10 * sizeof(int));
     x[10] = 0;        // problem 1: heap block overrun
  }                    // problem 2: memory leak -- x not freed

  int main(void)
  {
     f();
     return 0;
  }

4.1、内存溢出错误信息

运行valgrind的内存检查,错误信息如下:一个内存溢出的错误(heap block overrun)描述

  ==19182== Invalid write of size 4
  ==19182==    at 0x804838F: f (test.c:5)
  ==19182==    by 0x80483AB: main (test.c:10)
  ==19182==  Address 0x1BA45050 is 0 bytes after a block of size 40 alloc'd
  ==19182==    at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
  ==19182==    by 0x8048385: f (example.c:5)
  ==19182==    by 0x80483AB: main (example.c:11)

4.1.1、需要注意的事项

  • 每条错误信息都包含大量信息,请仔细阅读。
  • 19182 是进程 ID,通常并不重要。
  • 第一行(“Invalid write…”)告诉你是哪种错误。在这里,由于堆块超限,程序写入了一些不应该写入的内存。
  • 首行下面是堆栈跟踪,告诉你问题发生在哪里。堆栈跟踪可能会变的很大,而且容易混淆,尤其是在使用C++ STL的情况下,从下往上读堆栈跟踪是可以帮助我们梳理问题。如果堆栈跟踪不够大,可以使用–num-callers选项将其变大。
  • 如 0x804838F这样的地址,通常并不重要,但有时对追踪很奇怪的错误会有帮助。
  • 有些错误信息的第二个部分描述了所涉及的内存地址。这条信息显示,写入的内存刚过 example.c 第 5 行用 malloc() 分配的块的末尾。

值得注意的是,要按照错误报告的顺序修正错误,因为后面的错误可能是前面的错误造成的。没有做到这一点是造成 Memcheck 困难的常见原因。

内存泄漏的信息如下:

  ==19182== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
  ==19182==    at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
  ==19182==    by 0x8048385: f (test.c:5)
  ==19182==    by 0x80483AB: main (test.c,:10)

堆栈跟踪会告诉你泄露的内存是在哪里分配的。遗憾的是,Memcheck 无法告诉你内存泄漏的原因。(忽略 “vg_replace_malloc.c”,那是实现细节)。

4.2、泄漏有多种类型,其中最重要的有两类:

  • “definitely lost”: your program is leaking memory – fix it!
  • “probably lost”:your program is leaking memory, unless you’re doing funny things with pointers (such as moving them to point to the middle of a heap block).

Memcheck也会报告未初始化值的使用情况,常见的信息是"Conditional jump or move depends on uninitialised value(s)"。要确定这些错误的根本原因可能很困难。尝试使用 --track-origins=yes 获取更多信息。这虽然会降低 Memcheck 的运行速度,但获得的额外信息往往可以节省大量时间,从而找出未初始化值的来源。

如果你不理解错误信息,请查阅Valgrind用户手册中的Memcheck错误信息解释,其中有Memcheck生成的所有错误信息的示例。

五、注意事项

Memcheck 并不完美;它偶尔会产生误报,但也有抑制误报的机制(请参阅《Valgrind 用户手册》中的抑制错误)。不过,它通常 99% 的时间都是正确的,所以你应该警惕忽视它的错误信息。毕竟,你不会忽略编译器生成的警告信息,不是吗?如果 Memcheck 报告了你无法更改的库代码中的错误,抑制机制也很有用。默认的抑制设置会隐藏很多这样的错误,但你可能会遇到更多。

Memcheck 无法检测程序的所有内存错误。例如,它无法检测对静态分配或堆栈上的数组的超范围读取或写入。但它应该能检测出许多可能导致程序崩溃的错误(如导致分段故障)。

尽量使你的程序干净到 Memcheck 不报错。一旦达到这种状态,当程序发生变化导致 Memcheck 报告新错误时,就更容易发现了。多年使用 Memcheck 的经验表明,即使是庞大的程序,也有可能以干净的方式运行 Memcheck。例如,KDE、OpenOffice.org 和 Firefox 中的大部分程序都是 Memcheck-clean,或非常接近 Memcheck-clean。

六、更多信息

请查阅 Valgrind 常见问题和 Valgrind 用户手册,其中有更多信息。请注意,Valgrind 发行版中的其他工具可以通过 --tool 选项调用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值