C++ 的内存泄漏检测器






3.24/5 (9投票s)
2006年11月28日
4分钟阅读

78301

1622
用于调试内存泄漏的简单插件代码。
引言
这个简单的独立内存泄漏检测器可以直接插入到您的 C++ 项目中,只需在您的项目的预处理器设置或 makefile 中定义 DEBUG_MEMORY
,并在程序结束时调用 DumpUnfreed(TRUE);
,即可在程序退出时创建一个 memoryleak.txt 文件。您也可以在程序内的关键位置调用 DumpUnfreed()
。此代码具有很好的可移植性,可在任何 Windows、Linux 或 DOS 环境中运行。它也已经在 Linux 环境的 GCC 3.2.2 编译器和使用 Developer Studio 1.1 的 Win32 环境中进行了测试。DebugMemory
例程会覆盖 malloc()
, calloc()
, free()
, delete()
, new()
, delete[]
, 和 new[]
。memoryleak.txt 文件会打印出分配发生的文件和行号以及文件名,以及已分配缓冲区的地址及其大小。通过 DebugMemory
释放的、但未使用 DebugMemory
分配的任何地址也会在 memoryleak.txt 输出文件中注明。
除了创建内存泄漏报告之外,您还可以通过在程序的开头调用 DebugMemoryLogAllocations(TRUE);
来跟踪代码中的每个分配和释放。这将创建一个名为 debugmemorylog.txt 的文件,该文件显示通过 DebugMemory
接口运行的每次分配和释放。额外的日志记录会显着减慢程序的运行速度,因此此功能不适用于实时应用程序。
使用示例
zip 文件中包含另外两个 zip 文件,其中包含测试各种 new
/ delete
, malloc
, calloc
和 free
覆盖的示例。GCCSample.zip 包含一个带有 makefile 的 Linux 示例,Win32Sample.zip 包含一个 Windows Developer Studio 1.1 示例项目。该示例演示了通过 malloc
、calloc
分配标准内存块,并通过 free
释放这些块。它还展示了将 C++ 类分配为单个对象和类对象数组。该类的构造函数也通过 new
分配内存,并在其析构函数中删除该内存。此外,它还展示了一个派生类,该类实例化基类,并且派生类在其自己的构造函数中为其派生类局部成员分配内存。派生类在示例代码中被分配为单个对象以及对象数组。您可以使用 Visual Studio 调试器逐步调试分配,并观察内存分配系统的工作方式。
示例程序源代码对于这两个操作系统是相同的,并生成一个 debugmemorylog.txt 跟踪文件,其中包含每次分配和释放,以及一个 memoryleak.txt 输出文件。该示例将显示总共 175 次分配和 175 次释放,并且没有内存泄漏。
但是,如果您在主程序中取消注释第 126 和 127 行,它将再次运行标准库和 C++ 分配例程,但第二次运行时不会释放内存,并在 memoryleak.txt 文件中生成详细的内存泄漏报告。
// Uncomment these next two lines // if you want to see leaks in the memoryleak.txt file. //AllocStdLibStyle(FALSE); //AllocCPPStyle(FALSE);
使用代码
要在您的项目中使用该代码,请将 DebugMemory.cpp 和 DebugMemory.h 添加到您的项目或 makefile 中。将 DEBUG_MEMORY
定义为编译器的预处理器定义。在 stdafx.h 或另一个被您要调试的所有代码包含的 .h 文件中包含 DebugMemory.h。在您的代码中,在程序退出之前添加例程 DumpUnfreed(TRUE);
。编译并测试。
// Add a call to DumpUnfreed(TRUE) at the end of your // program to write the memoryleaks.txt file // and find any leaks in your program. // // Passing TRUE to DumpUnfreed() will free the list // of memory block breadcrumbs that the DebugMemory utility uses to // keep track of the memory allocated by your program. // If you do not want to free the list, pass FALSE instead of TRUE. DumpUnfreed(TRUE); exit(0);
关注点
DebugMemory
使用的内存块的面包屑跟踪会根据实用程序的需要动态增长,因此您无需担心设置一些预定义的大小。列表的内存分配不是 DebugMemory
跟踪的一部分。
请注意,单例、具有静态或全局范围且在其构造函数中分配内存的 C++ 对象,当您在程序退出之前调用 DumpUnfreed()
时,将显示为泄漏,因为它们的标量析构函数直到程序作为 exit(0)
的一部分卸载时才会被调用。
如果您选择将此代码用于 Microsoft VC++、Developer Studio 或 GCC 3.2.2 之外的编译器,您可能需要更改使用预处理器 __cdecl
, __FILE__
和 __LINE__
的原型,以替换为适合您的编译器的原型。但是,该代码应该很容易移植到其他编译器环境中,因为它不需要任何除标准 C 运行时库元素之外的内容。