Valgrind快速入门指南

Table of Contents

1.简介

2.准备程序

3.在Memcheck下运行程序

4.解释Memcheck的输出

5.注意事项

6.更多信息


https://www.valgrind.org/docs/manual/quick-start.html#quick-start.intro

1.简介

Valgrind工具套件提供了许多调试和性能分析工具,可帮助您使程序更快,更正确。这些工具中最流行的称为Memcheck。它可以检测到许多与内存有关的错误,这些错误在C和C ++程序中很常见,并且可能导致崩溃和不可预测的行为。

本指南的其余部分提供了使用Memcheck开始检测程序中的内存错误所需的最少信息。有关Memcheck和其他工具的完整文档,请阅读用户手册。

2.准备程序

编译程序-g以包含调试信息,以便Memcheck的错误消息包含确切的行号。-O0如果可以忍受减速,使用也是一个好主意。随着 -O1错误消息的行号可能不准确,但总体上说,在上编译代码运行MEMCHECK -O1作品相当不错,而且速度提高相比,运行-O0是相当显著。-O2不建议使用 及以上版本,因为Memcheck偶尔会报告实际上不存在的未初始化值错误。

3.在Memcheck下运行程序

如果正常运行程序是这样的:

 myprog arg1 arg2

使用以下命令行:

  valgrind --leak-check=yes myprog arg1 arg2

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

您的程序将比正常运行慢得多(例如20到30倍),并且使用更多的内存。Memcheck将发出有关内存错误和它检测到的泄漏的消息。

4.解释Memcheck的输出

这是一个名为ac的文件中的示例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;
  }

大多数错误消息如下所示,它描述了问题1,堆块溢出:

  ==19182== Invalid write of size 4
  ==19182==    at 0x804838F: f (example.c:6)
  ==19182==    by 0x80483AB: main (example.c:11)
  ==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)

注意事项:

  • 每个错误消息中都有很多信息;仔细阅读。

  • 19182是进程ID;通常并不重要。

  • 第一行(“无效写入...”)告诉您这是哪种错误。在这里,由于堆块溢出,程序向其不应有的内存中写入数据。

  • 第一行下方是一个堆栈跟踪,告诉您问题出在哪里。堆栈跟踪可能会变得很大,并且会造成混乱,尤其是在使用C ++ STL的情况下。从头开始阅读它们会有所帮助。如果堆栈跟踪不够大,请使用该--num-callers选项将其增大。

  • 代码地址(例如0x804838F)通常并不重要,但有时对于跟踪怪异的bug至关重要。

  • 某些错误消息具有第二个组件,该组件描述了所涉及的内存地址。这表明在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 (a.c:5)
  ==19182==    by 0x80483AB: main (a.c:11)

堆栈跟踪告诉您泄漏内存的分配位置。不幸的是,Memcheck无法告诉您为什么内存泄漏。(忽略“ vg_replace_malloc.c”,这是一个实现细节。)

有几种泄漏;两个最重要的类别是:

  • “绝对丢失”:您的程序正在泄漏内存-对其进行修复!

  • “可能丢失”:您的程序正在泄漏内存,除非您使用指针做一些有趣的事情(例如将它们移至指向堆块的中间)。

Memcheck还报告未初始化值的使用,最常见的消息是“条件跳转或移动取决于未初始化值”。确定这些错误的根本原因可能很困难。尝试使用--track-origins=yes获取更多信息。这使Memcheck的运行速度变慢,但是您经常获得的额外信息可以节省大量时间来确定未初始化值的来源。

如果您不理解错误消息,请查阅 《Valgrind用户手册》中有关Memcheck的错误消息说明, 其中提供了Memcheck产生的所有错误消息的示例。

5.注意事项

Memcheck并不完美;它偶尔会产生误报,并且有一些抑制误报的机制(请参见 《Valgrind用户手册》中的“ 抑制错误)。但是,通常99%的时间是正确的,因此您应该警惕忽略其错误消息。毕竟,您不会忽略编译器生成的警告消息,对吗?如果Memcheck在无法更改的库代码中报告错误,则抑制机制也很有用。默认的抑制设置隐藏了很多这些,但您可能会遇到更多。

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

尝试使您的程序干净整洁,以使Memcheck不会报告任何错误。一旦达到此状态,就更容易看到程序更改何时导致Memcheck报告新错误。多年使用Memcheck的经验表明,甚至可以使大型程序运行干净的Memcheck。例如,KDE,OpenOffice.org和Firefox的大部分都是Memcheck-clean,或者非常接近。

6.更多信息

请查阅《Valgrind FAQ》和《 Valgrind用户手册》,其中包含更多信息。请注意,可以使用该--tool选项调用Valgrind发行版中的其他工具 。

 

©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页