C++ operator new[]和Debug Heap
如果在VS2005下面想用CRT Debug Heap來除錯Memory Leak,最後可以用_CrtDumpMemoryLeaks把所有的leak打印出來。嘗試下面的程式碼,會怎樣:
#include "stdafx.h"
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include<stdlib.h>
#include<crtdbg.h>
#endif
#define MY_NEW[s] new(s,_NORMAL_BLOCK, __FILE__, __LINE__)
#if defined(_DEBUG) && defined
#define new MY_NEW
#endif
int _tmain(int argc, _TCHAR* argv[])
{
char *p=new char[10];
void *p2=malloc(10);
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif
return 0;
}
執行後會看到:
Detected memory leaks!
Dumping objects ->
c:/documents and settings/lixiong/my documents/mycode/detectleak/detectleak/detectleak.cpp(17) : {87} normal block at 0x003A8130, 10 bytes long.
Data: <> CD CD CD CD CD CD CD CD CD CD
c:/program files/microsoft visual studio 8/vc/include/crtdbg.h(1150) : {86} normal block at 0x003A3240, 10 bytes long.
Data: <> CD CD CD CD CD CD CD CD CD CD
Object dump complete.
The program '[808] DetectLeak.exe: Native' has exited with code 0 (0x0).
注意這裡打印出的第一個
可是第二個leak,出現在crtdbg.h的1150行,而不是new char[10]那裡,怎麼回事?如果不能定位到正確的原始碼,還有什麼用呢?
為了搞清楚這個問題,可以看看malloc在debug heap下的的定義:
#ifdef_CRTDBG_MAP_ALLOC
#definemalloc(s)_malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
注意看,這裡用了__FILE__, __LINE__兩個前處理器Directive:
由於與處理器自動把檔名和行號傳遞給了_malloc_dbg函式,最後的output窗口才可以打印出原始碼行
那好,看看debug heap的new的定義。由於new是C++的關鍵字,而且是一個操作符,所以debug heap下定義為:
inline __bcount(_Size) void* __CRTDECL operator new[](size_t _Size)
{ return ::operator new[](_Size, _NORMAL_BLOCK, __FILE__, __LINE__); }
注意這裡沒有用#define,而是inline。同時該定義是在crtdbg.h檔案中的。所以最後得到的是檔名是crtdbg.h。你可能有如下疑問:
1.為什麼不用#define而要用inline呢,改成#define可以嗎?你試試看吧,看能不能該成#define。由於這裡有一箇中括號,麻煩來了吧。誰讓你是C++呢?bs一下C++
2.為什麼前處理器看到inline函式,不把inline後的行號和檔名字作為解釋呢?這我就不確定了啦。不過根據C++標準,標示為inline函式不是一定就要inline的,人家標準就定義得模稜兩可,你何必強求前處理器呢?
所以,解決方法就是,所有的記憶體分配,就用:
#ifdef _CRTDBG_MAP_ALLOC
char *test=(char*)::operator new[](20, _NORMAL_BLOCK, __FILE__, __LINE__);
#else
char *test=new char[20];
#endif
你有其它好方法嗎?