重載全局new/delete實現(xiàn)內(nèi)存檢測下面介紹用重載new/delete運算符的方式來實現(xiàn)一個簡單的內(nèi)存泄露檢測工具,基本思想是重載全局new/delete運算符,被檢測代碼調(diào)用new和delete運算符時就會調(diào)用重載過的operator new和operator delete,在重載的operator new里和operator delete里記錄下內(nèi)存申請和釋放信息,從而判斷內(nèi)存使用情況。 下面一步步介紹它的實現(xiàn)! 1、 全局new/delete的重載 先看一下重載new/delete的規(guī)則: 重載的operator new的參數(shù)個數(shù)任意,但第一個參數(shù)必須是size_t類型的,返回值必須是void*。重載operator delete只允許有一個參數(shù),且是void*型。 當然,不光要重載operator new 和 operator delete, 還要重載operator new [], operator delete [],更多operator new和operator delete重載的內(nèi)容參考《Effective C++》 重載的new/delete, new[]/delete[]代碼如下: void * operator new (size_t size){ if(0 == size){ return 0; } void *p = malloc(size); return p; }
void * operator new [](size_t size){ return operator new(size); }
void operator delete (void * pointer){ if(0 != pointer){ free(pointer); } }
void operator delete[](void * pointer){ operator delete(pointer); }
2、 用__FILE__, __LINE__記錄new的位置 為了找到內(nèi)存泄露的元兇,我要記錄下每一處new所在的文件名和所在行。于是再次重載了operator new: void * operator new (size_t size, const char* file, const size_t line); void * operator new [](size_t size, const char* file, const size_t line); 為了避免編譯時出現(xiàn)warning C4291(沒有與operator new(unsigned int,const char *,const unsigned int) 匹配的delete),又重載了 void operator delete (void * pointer, const char* file, const size_t line); void operator delete[](void * pointer, const char* file, const size_t line); 盡管我知道它沒用。 我想到了用系統(tǒng)提供的__FILE__和 __LINE__宏獲取當前文件名與行號,我試圖把__FILE__和 __LINE__直接填到operator new和operator new[]函數(shù)體里邊,然后把函數(shù)置成inline,結(jié)果都輸出的是重載operator new和operator new[]的文件和函數(shù)體printf函數(shù)所在行。然后又試了將operator new的缺省參數(shù)設為__FILE__和 __LINE__結(jié)果依然,于是想到了用宏定義。 先看看MFC里的做法,MFC為了調(diào)試方便,對new進行了宏定義: #define new DEBUG_NEW #define DEBUG_NEW new(THIS_FILE, __LINE__)
這里我借用MFC的做法,我也用宏定義: void * operator new (size_t size, const char* file, const size_t line); void * operator new [](size_t size, const char* file, const size_t line); #define MC_NEW new(__FILE__, __LINE__) #define new MC_NEW
3、 將malloc/free 用new/delete替換 為了便于統(tǒng)計malloc/free信息,也用宏定義的方法處理: #define malloc(s) ((void*)new unsigned char[s]) #define free(p) (delete [] (char*)(p));
4、 在數(shù)據(jù)結(jié)構(gòu)里存儲內(nèi)存使用情況。 下面寫一個用于存儲new/delete中內(nèi)存信息的數(shù)據(jù)結(jié)構(gòu),可以使用鏈表,也可以使用哈希表,這里選用哈希表,寫一個CHash類。 代碼略。
5、 為了保證CHash在所有對象析構(gòu)執(zhí)行完之后再銷毀,應該將CHash放在全局存儲區(qū),將其設成static類型,另外,如果有多個static,還需要注意放置的順序。
到這里這個簡易的內(nèi)存泄露檢測工具完成了,但目前還不能用于多線程。
|
|
|