1. 程式人生 > >C++ operator new[]和Debug Heap

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

(_CRTDBG_MAP_ALLOC)

#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,出現在detectleak.cpp17行,對應的是malloc語句,沒問題

可是第二個leak,出現在crtdbg.h1150行,而不是new char[10]那裡,怎麼回事?如果不能定位到正確的原始碼,還有什麼用呢?

為了搞清楚這個問題,可以看看mallocdebug heap下的的定義:

#ifdef_CRTDBG_MAP_ALLOC

#definemalloc(s)_malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)

注意看,這裡用了__FILE__, __LINE__兩個前處理器Directive:

由於與處理器自動把檔名和行號傳遞給了_malloc_dbg函式,最後的output窗口才可以打印出原始碼行

那好,看看debug heapnew的定義。由於newC++的關鍵字,而且是一個操作符,所以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

你有其它好方法嗎?