我想使用标准实用程序在应用程序中查找内存泄漏。 以前我用我自己的内存分配器,但其他人(是的,你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中看到它的日志,但是我没有看到内存泄漏。
问题:
如果我没有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更有用,因为它会显示用于内存分配的完整调用堆栈已导致泄漏。