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

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

#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; } 

这个testing显然包含一个内存泄漏:p2是new'd,但不会被删除。

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

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

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

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

问题:

  • 为什么Application Verifier没有报告泄漏?
  • 还是不是应用程序validation程序真正打算find泄漏?
  • 如果在应用程序结束时没有其他工具可用来清楚地报告泄漏(即不是通过定期快照并比较它们,因为在1GB或更多的应用程序中这是不可能的),包括调用堆栈分配的地点(所以不是CRT末端的简单泄漏报告)

如果我没有find一个体面的工具,我仍然需要依靠自己的内存pipe理器(这是完美的)。

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

 // debug_new.h
 #pragma一次

 #include“crtdbg.h”

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

所有.cpp文件:

 #include“debug_new.h”

 ...

 //在所有其他包含行之后:
 #ifdef _DEBUG
 #定义新的DEBUG_NEW
 #万一

 ...

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

 _CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); 

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

 #ifdef _DEBUG
 #定义新的DEBUG_NEW
 #万一

限制:这只捕获“新的”内存泄漏,所有由另一个函数(如malloc)引起的泄漏都不会被捕获。

不要在.h文件中进行任何分配,因为DEBUG_NEW是在所有的#include行之后定义的,所以它们将被打印出来而没有源代码行。

应用程序验证程序只捕获DLL中的泄漏。 尝试阅读泄漏复选框中的工具提示。 这就是它所说的。

最简单的解决方案不是首先写入泄漏或缓冲区溢出 – 在事件发生后检测它们真的是浪费精力。 在我自己的规范中,多年来我在这些领域没有任何问题。 为什么? Becauase我使用C ++提供的机制来避免它们。 例如:

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

应该:

 shared_ptr <X> p1 = new X(); 

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

 X x1; 

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

我不敢夸耀自己在避免内存泄漏方面的实力 – 这些东西确实有效,并且允许您继续调试代码的业务逻辑,这是一项非常困难的任务。

我有一种感觉,Application Verifier特殊情况下是退出路径,并不会将这些标记为泄漏 – 毕竟,整个进程堆在进程退出时都是空闲的。

尝试再次初始化同一个指针时写另一个示例 – 基本上失去了对以前分配的引用。 这当然应该被标记。 让我知道结果。

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

内存验证从软件验证将捕获内存泄漏,并显示完整的调用堆栈泄漏的分配。 虽然它是一个商业产品,但它有一个试用期,所以程序员可以尝试一下,看看它是否物有所值。

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