Valgrind *不是* 泄漏检查工具

在我的社区中,Valgrind 是我已知的被误解最深的工具。Valgrind 不仅仅是一个内存泄露检查器。它只是包含了一个检查内存泄露的工具而已。但我想说的是这个工具恰恰是 Valgrind 中用处最小的一个组件。

无需改变 Valgrind 的调用方式,你就能得到比大多数人想象的要多得多的极具价值的信息。 Valgrind 会在你的程序奔溃之前找出潜在的错误;它不仅告诉你错误在哪里,还会告诉你原因(用英语哦). Valgrind 首先是一个未知行为 检测工具,其次他是一个函数和内存分析工具, 然后是一个数据竞争条件侦测工具, 它最后才是一个内存泄露检查工具。

首先也是最重要的:

要运行 Valgrind, 你只需切换到你程序所在的目录然后运行如下命令:

valgrind ./myProgram myProgramsFirstArg myProgramsSecondArg

无需特殊的参数。

你将会同时看到你的程序的输出,以及由 Valgrind 生成的调试输出信息(那些 ‘==‘ 开头的行)。如果你的程序在编译生成时带了 -g 选项(生成调试符号信息),Valgrind 将提供更多有帮助的信息(比方说执行代码的行号)。

基于本文的目的, 请 忽略所有 Valgrind 输出内容里 "HEAD SUMMARY" 行之后的内容。 这正是本文不关心的部分:内容泄露摘要。

Linux下Valgrind的使用概述

Linux下利用Valgrind工具进行内存泄露检测和性能分析

Ubuntu 内存泄漏检测工具Valgrind的安装

Valgrind--Linux下的内存调试和代码解剖工具

应用 Valgrind 发现 Linux 程序的内存问题[图文]

它能检测到些什么呢?

1) 误用未初始化的值. 这也是它的基本功:

bool condition;
if (condition) {
  //Do the thing
}

有趣的是,大部分时间里你的程序只是继续运行,然后当运行到这里时,毫无征兆的出现运行失败。 它可能(大多数时候)看似在按你预想的那样的运行。理论上,如果你的程序有错误,那每次运行它它都应该出错。这些错误是硬性的,很快就能显现出来。只有先确定哪里有错误,然后我们才能修复它。问题是我们从一开始就没有赋予那个布尔变量任何值,它也不会被程序自动的初始化. 此时,它的值可能是任何恰好留在它的内存位置上的随机的值。

上面实例中 Valgrind 会输出这样的行:

==2364== Conditional jump or move depends on uninitialized value(s)
==2364==    at 0x400916: main (test.cpp:106)

注意:上述输出给出了代码会引发未知行为的原因,不光只是位置。更棒的是,Valgrind 在这些未知行为引发程序崩溃之前就捕捉到了他们。

像上面那样显而易见的错误估计很难出现,但下面这个错误估计就没那么好发现了:

bool condition;
if (foo) {
  condition = true;
}
if (bar) {
  condition = false;
}
if (baz) {
  condition = true;
}
if (condition) {
  //Do the thing
}

这里我们只有某些时候成功地初始化了condition,但不是全部。Valgrind仍然可以检查出这些未定行为。

使用某些防御性编程的方法可以从根源避免这种错误。我比较倾向于给每一个变量一个初始值。或是使用auto关键字来强迫你去初始化某个变量(在没有一个值的情况下,你不能推断出那个变量的类型)。你可以看看Herb Sutter的博客 ,里面提到了更多关于auto关键字的事情。 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/17137.html