如何使用Application Verifier查找内存泄漏

时间:2010-06-02 07:52:38

标签: c++ windows memory-leaks application-verifier

我想使用标准实用程序在我的应用程序中查找内存泄漏。 以前我使用自己的内存分配器,但其他人(是的,你AlienFluid)建议使用微软的应用程序验证程序,但我似乎无法报告我的泄漏。 我有以下简单的应用程序:

#include <iostream>
#include <conio.h>

class X
   {
   public:
      X::X() : m_value(123) {}
   private:
      int m_value;
   };

void main()
{
X *p1 = 0;
X *p2 = 0;
X *p3 = 0;

p1 = new X();
p2 = new X();
p3 = new X();
delete p1;
delete p3;
}

此测试显然包含内存泄漏:p2是新的但未删除。

我使用以下命令行构建可执行文件:

cl /c /EHsc /Zi /Od /MDd test.cpp
link /debug test.obj

我下载了应用验证程序(4.0.0665)并启用了所有检查。

如果我现在运行我的测试应用程序,我可以在Application Verifier中看到它的日志,但我没有看到内存泄漏。

问题:

  • 为什么Application Verifier没有报告泄漏?
  • 或者应用程序验证程序真的不是要查找泄漏吗?
  • 如果没有哪些其他工具可用于在应用程序结束时清楚地报告泄漏(即不是通过拍摄常规快照并进行比较,因为这在1GB或更多的应用程序中是不可能的),包括呼叫分配地点的堆栈(因此不是CRT结束时的简单泄漏报告)

如果我找不到合适的实用程序,我仍然需要依靠自己的内存管理器(完美地完成它)。

6 个答案:

答案 0 :(得分:4)

CRT内存泄漏检测(没有堆栈跟踪):

// debug_new.h
#pragma once

#include "crtdbg.h"

#ifdef _DEBUG
#ifndef DEBUG_NEW
#define DEBUG_NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#endif

所有.cpp文件:

#include "debug_new.h"

...

// After all other include lines:
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

...

在程序初始化代码中写一次:

_CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

在MFC中,所有这些都已在MFC标头中实现。您只需要确保每个cpp文件都包含以下行:

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

限制:这只捕获“新的”内存泄漏,由malloc等其他函数引起的所有泄漏都不会被捕获。

不要在.h文件中进行任何分配 - 它们将在没有源行的情况下打印,因为DEBUG_NEW是在所有#include行之后定义的。

答案 1 :(得分:4)

Application Verifier仅捕获DLL中的泄漏。尝试阅读泄漏复选框中的工具提示。这就是它所说的。

答案 2 :(得分:1)

我有一种感觉,Application Verifier特殊情况下的退出路径并没有将这些标记为泄漏 - 毕竟,整个进程堆在进程退出时是免费的。

尝试再次初始化相同指针的另一个示例 - 基本上丢失对先前分配的引用。这肯定会被标记出来。让我知道结果。

另外,AppVerifier(如果你启用了所有选项)也应该捕获缓冲区溢出,下溢,写入标记为RO等的堆栈位置。

答案 3 :(得分:1)

来自Software Verification的内存验证程序将捕获内存泄漏,并显示泄漏分配的完整callstack。虽然它是一个商业产品,但它有一个试用期,所以程序员可以试一试,看看它是否物有所值。

答案 4 :(得分:0)

最简单的解决方案是不要在第一时间写入泄漏或缓冲区溢出 - 在事件真正浪费精力后检测它们。在我自己的代码中,多年来我在这些方面都没有问题。为什么?我使用C ++提供的机制来避免它们。例如:

X *p1 = 0;
p1 = new X();

应该是:

shared_ptr <X>  p1 = new X();

你不再担心p1泄漏。更好的是,根本不要使用动态分配:

X x1;

对于缓冲区溢出,总是使用类似std :: string的类型,这些类型将在输入时增长,或者如果它们不增长将检测可能的溢出并警告你。

我并没有吹嘘我在避免内存泄漏方面的实力 - 这些东西确实有用,并且允许您继续调试代码的业务逻辑这一更困难的任务。

答案 5 :(得分:0)

Visual Leak Detector(v2.2)比CRT Debug Library更有用,因为它会显示用于内存分配的完整callstack导致泄漏。