内存泄露检查

Windows平台下的内存泄露

使用CRTDBG

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK

int main()
{
	char * p = new char[10];
	_CrtMemDumpAllObjectsSince(nullptr); // or _CrtDumpMemoryLeaks();
	return 0;
}

F5Debug输出内容为:

Dumping objects ->
d:\dev\csharptest\cpptest\main.cpp(262) : {236} client block at 0x00265C78, subtype 0, 10 bytes long.
 Data: <          > CD CD CD CD CD CD CD CD CD CD
Object dump complete.

从上面的宏可以看出来,将new重新宏定义为 new( _CLIENT_BLOCK, __FILE__, __LINE__)这样就可以定位到出现泄露的分配代码行。

如果没有macro new则只是打印出有多少的内存泄露。

从这里我们将会详细讨论CRT Debug Heap来检查内存泄露。

首先CRT Debug只针对与托管代码,也就是C++。

使用CRTDGB,需要按照如下顺序引用头文件,否则将会产生失败。

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
宏_CRTDBG_MAP_ALLOC的作用是编译期中使用了crtdbg.h的_malloc_dbg 与 free来代替原有的malloc与free,如果你不define这个宏,你将需要将使用new的地方显示调用_malloc_dbg函数。这样也说明只能在_DEBUG宏下使用这个已经转义的malloc与free。如果是release,则使用原有的malloc与free函数。由于crtdbg.h对_malloc_dbg进行重新定义,记录的分配内存的细节,大少,代码文件以及对应的行数。

void *_malloc_dbg(
   size_t size,
   int blockType,
   const char *filename,
   int linenumber 
);
通过函数的定义,size是由于new提供的(原有的new也是传递字节数给原有的malloc函数),后面的_CLIENT_BLOCK, __FILE__, __LINE__分别赋值于blockType, filename, linenumber。
_CrtDumpMemoryLeaks();

该函数将内存泄露信息打印到Debug面板中的Output窗口,同时该函数需要放置在程序退出前调用。如果程序中有很多异常处理导致可能程序退出的位置有很多,可以在程序入口出使用如下代码,它会在程序退出前自动调用_CrtDumpMemoryLeaks()函数。

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

如果需要打印详细的内存分配情况可以使用Statistics函数,同时可以定位到具体调用内存分配(我没有成功实现过。。。)

	_CrtMemState s1, s2, s3;
	char * _p = nullptr;
	_CrtMemCheckpoint(&s1);
	GetMemory(_p, 10);
	_CrtMemCheckpoint(&s2);
	if (_CrtMemDifference(&s3, &s1, &s2))
		_CrtMemDumpStatistics(&s3);
	
建立3个信息对象,然后在分配内存操作的前后通过调用_CrtMemCheckpoint捕抓信息,接着使用_CrtMemDifference对比两者信息然后通过_CrtMemDumpStatistics打印信息。

使用Visual Leak Detector

下载visual leak detector并且安装

添加环境变量VLD并且在项目的头文件添加$(VLD)\include,在link搜索库中添加$(VLD)\lib\Win$(PlatformArchiteture)\

编译代码通过DEBUG运行程序,内存泄露信息将出现在DEBUGpanel的Output窗口中。

---------- Block 1 at 0x003B5328: 10 bytes ----------
  Call Stack:
    d:\dev\csharptest\cpptest\main.cpp (121): cpptest.exe!GetMemory + 0x9 bytes
    d:\dev\csharptest\cpptest\main.cpp (262): cpptest.exe!main + 0xB bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): cpptest.exe!__tmainCRTStartup + 0x19 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): cpptest.exe!mainCRTStartup
    0x75B93677 (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
    0x77069F42 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
    0x77069F15 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
  Data:
    CD CD CD CD    CD CD CD CD    CD CD                          ........ ........
通过上面可以看到使用vld的好处时使用简单,就是安装一个库,同时在代码中引用头文件而已,可以通过宏预编译来控制是否进行内存泄露检查。

Linux平台下内存泄露

待补
















原文地址:https://www.cnblogs.com/rogerroddick/p/2846705.html