重載全局new/delete實現內存檢測

下面介紹用重載new/delete運算符的方式來實現一個簡單的內存泄露檢測工具,基本思想是重載全局new/delete運算符,被檢測代碼調用new和delete運算符時就會調用重載過的operator new和operator delete,在重載的operator new裏和operator delete裏記錄下內存申請和釋放信息,從而判斷內存使用狀況。數據結構

下面一步步介紹它的實現!多線程

一、  全局new/delete的重載函數

先看一下重載new/delete的規則:工具

重載的operator new的參數個數任意,但第一個參數必須是size_t類型的,返回值必須是void*。重載operator delete只容許有一個參數,且是void*型。.net

固然,不光要重載operator new 和 operator delete, 還要重載operator new [], operator delete [],更多operator new和operator delete重載的內容參考《Effective C++》線程

重載的new/delete, new[]/delete[]代碼以下:調試

void * operator new (size_t size){對象

if(0 == size){blog

        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);

}

 

二、  用__FILE__, __LINE__記錄new的位置

爲了找到內存泄露的元兇,我要記錄下每一處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);

爲了不編譯時出現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);

              儘管我知道它沒用。

我想到了用系統提供的__FILE__和 __LINE__宏獲取當前文件名與行號,我試圖把__FILE__和 __LINE__直接填到operator new和operator new[]函數體裏邊,而後把函數置成inline,結果都輸出的是重載operator new和operator new[]的文件和函數體printf函數所在行。而後又試了將operator new的缺省參數設爲__FILE__和 __LINE__結果依然,因而想到了用宏定義。

先看看MFC裏的作法,MFC爲了調試方便,對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

 

 

三、  將malloc/free 用new/delete替換

爲了便於統計malloc/free信息,也用宏定義的方法處理:

#define malloc(s) ((void*)new unsigned char[s])

#define free(p)   (delete [] (char*)(p));

 

四、  在數據結構裏存儲內存使用狀況。

            下面寫一個用於存儲new/delete中內存信息的數據結構,可使用鏈表,也可使用哈希表,這裏選用哈希表,寫一個CHash類。

代碼略。

 

五、  爲了保證CHash在全部對象析構執行完以後再銷燬,應該將CHash放在全局存儲區,將其設成static類型,另外,若是有多個static,還須要注意放置的順序。

相關文章
相關標籤/搜索