9

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

#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

我下载了 Application Verifier (4.0.0665) 并启用了所有检查。

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

问题:

  • 为什么应用程序验证程序不报告泄漏?
  • 或者应用程序验证器不是真的打算找到泄漏吗?
  • 如果不是哪些其他工具可用于在应用程序结束时清楚地报告泄漏(即不是通过定期拍摄快照并比较它们,因为这在占用 1GB 或更多的应用程序中是不可能的),包括分配位置(所以不是 CRT 末尾的简单泄漏报告)

如果我没有找到一个像样的实用程序,我仍然必须依靠我自己的内存管理器(它做得很好)。

4

7 回答 7

4

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

// debug_new.h
#pragma 一次

#include "crtdbg.h"

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

所有 .cpp 文件:

#include “debug_new.h”

...

// 在所有其他包含行之后:
#ifdef _DEBUG
#define new DEBUG_NEW
#万一

...

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

_CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

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

#ifdef _DEBUG
#define new DEBUG_NEW
#万一

限制:这仅捕获“新”内存泄漏,不会捕获由其他函数(如 malloc)引起的所有泄漏。

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

于 2010-06-02T09:05:10.260 回答
4

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

于 2011-05-04T02:32:58.013 回答
1

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

于 2012-06-18T16:33:28.243 回答
1

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

尝试编写另一个示例,在其中再次初始化相同的指针 - 基本上会丢失对先前分配的引用。这当然应该被标记。让我知道结果。

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

于 2010-06-04T00:04:22.640 回答
0

最简单的解决方案是一开始就不写泄漏或缓冲区溢出——在事件发生后检测它们真的是浪费精力。在我自己的代码中,多年来我在这些领域的问题为零。为什么?因为我使用 C++ 提供的机制来避免它们。例如:

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

应该:

shared_ptr <X>  p1 = new X();

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

X x1;

对于缓冲区溢出,请始终使用 std::string 这样的类型,它会在输入时增长,或者如果它们不增长,则会检测到可能的溢出并警告您。

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

于 2010-06-02T09:14:48.240 回答
0

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

于 2011-10-28T17:15:14.820 回答
0

应用程序验证器不是这项工作的正确工具,但我仍然建议您启用应用程序验证器检查。Windows 上等效的UMDH(用户模式转储堆),它是一个命令行工具。

我的一位前同事写了UMDH Gui至少有一些可用性。

于 2022-01-13T12:16:25.773 回答