介绍几种常见平台下的内存泄露检测工具

Visual C++ 在 Windows 系统下查找和修复内存泄露

使用方法

Microsoft Visual C++中,其调试库内建了对内存泄漏的支持;

对于下面这个代码:

#include <iostream>

int main(){
    int* p0 = new int{};
    int* p1 = new int{};
    int* p2 = new int{};
    int* p3 = new int{};
    int* p4 = new int{};
    
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

这个内存泄漏检测功能默认情况下没有启用,除非创建的是MFC项目;

其具体的使用方法如下:
在代码的开头添加一下三行代码:

#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>
  • 1.
  • 2.
  • 3.

接下来,需要重新定义new运算符:

#ifdef _DEBUG
	#ifndef DBG_NEW
		#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
		#define new DBG_NEW
	#endif
#endif
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

注意这里新定义的new运算符在ifdef _DEBUG语句中,所以只有在编译调试版的应用程序时,才会使用新的new

而由于性能原因,发行版通常不会执行对内存泄露的任何检测;

最后,需要在main函数的第一行中添加下面这行代码:

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  • 1.

这行代码告诉Visual C++ CRT(C运行时)库,在应用程序退出时,将所有检测到的内存泄露写入调式输出控制台(注意这里需要使用调用模式),对于内存泄露的程序(如上所示),其调试控制台应该会包含类似一下的输出:

Detected memory leaks!
Dumping objects ->
D:\Code_Set\Code C++\C++20\test.cpp(86) : {175} normal block at 0x000001ED32E66D80, 4 bytes long.
 Data: <    > 00 00 00 00 
D:\Code_Set\Code C++\C++20\test.cpp(85) : {174} normal block at 0x000001ED32E66D40, 4 bytes long.
 Data: <    > 00 00 00 00 
D:\Code_Set\Code C++\C++20\test.cpp(84) : {173} normal block at 0x000001ED32E67300, 4 bytes long.
 Data: <    > 00 00 00 00 
D:\Code_Set\Code C++\C++20\test.cpp(83) : {172} normal block at 0x000001ED32E66D00, 4 bytes long.
 Data: <    > 00 00 00 00 
D:\Code_Set\Code C++\C++20\test.cpp(82) : {171} normal block at 0x000001ED32E67700, 4 bytes long.
 Data: <    > 00 00 00 00 
Object dump complete.
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
输出解释

如上所示,这里清晰的显示出了哪个文件的哪一行内存没有释放;文件名后面的括号中的数字就是行号;

大括号之间的数字是内存分配的计数器,例如这里的{175}表示这是程序开始之后进行的第175次分配;

可以使用VC++_CrtSetBreakAlloc()函数告诉Visual C++运行时,进行特定分配时进入调试器,例如:

_CrtSetBreakAlloc(175);

修复内存泄露

但是这里的Visual C++和下面的Valgrind这类程序都不能实际修复内存泄露,而是提供了观察点(watch point)功能,用于在发生这类事件时中断程序的执行;

通过 Valgrind 在 Linux 中查找和修复内存泄露