過載全域性new delete實現記憶體檢測

2021-10-01 06:51:32 字數 2946 閱讀 8427

下面介紹用過載new/delete運算子的方式來實現乙個簡單的記憶體洩露檢測工具,基本思想是過載全域性new/delete運算子,被檢測**呼叫new和delete運算子時就會呼叫過載過的operator new和operator delete,在過載的operator new裡和operator delete裡記錄下記憶體申請和釋放資訊,從而判斷記憶體使用情況。

下面一步步介紹它的實現!

1、全域性new/delete的過載

先看一下過載new/delete的規則:

過載的operator new的引數個數任意,但第乙個引數必須是size_t型別的,返回值必須是void*。過載operator delete只允許有乙個引數,且是void*型。

當然,不光要過載operator new 和 operator delete, 還要過載operator new , operator delete ,更多operator new和operator delete過載的內容參考《effective c++》

過載的new/delete, new/delete**如下:

void * operator new (size_t size)

void *p = malloc(size);

return p;

}void * operator new (size_t size)

void operator delete (void * pointer)

}void operator delete(void * pointer)

2、用__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

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

為了便於統計malloc/free資訊,也用巨集定義的方法處理:

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

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

4、在資料結構裡儲存記憶體使用情況。

下面寫乙個用於儲存new/delete中記憶體資訊的資料結構,可以使用鍊錶,也可以使用雜湊表,這裡選用雜湊表,寫乙個chash類。

**略。

5、為了保證chash在所有物件析構執行完之後再銷毀,應該將chash放在全域性儲存區,將其設成static型別,另外,如果有多個static,還需要注意放置的順序。

到這裡這個簡易的記憶體洩露檢測工具完成了,但目前還不能用於多執行緒。

①當兩個operator new和operator delete有相等的引數個數,並且除了第乙個引數之外其餘引數的型別依次完全相同之時,我們稱它們為一對匹配的operator new和operator delete。

不過正常情況下帶多個引數的delete不會被呼叫,只有在構建乙個物件的過程中,建構函式中發生異常,並且這個異常**獲了,那麼此時c++的異常處理機制才會自動用與被使用的operator new匹配的operator delete來釋放記憶體(補充一點:在operator new中丟擲異常不會導致這樣的動作,因為系統認為這標誌著記憶體分配失敗)。

試驗**:

#include

struct base

~base() {}

void* operator new( size_t nsize, const char*,int)

void operator delete( void *p)

void operator delete( void* p,const char*,int)

};#define new new(__file__, __line__)

int main( void )

catch(...)

return 0;

}

過載全域性new,delete

過載全域性new,delete 對與new操作符,其實和sizeof一樣,都是c 內建的,然而像strlen就不是了,strlen屬於函式。對於new的功能我們是沒有辦法改變 的,當我們new乙個物件時,new為我們做了兩件事情,一 申請一塊足夠的記憶體空間供存放物件,對於new乙個陣列物件,編譯器...

c 中的過載全域性new,delete

這樣我們每次呼叫new,比如int pn new int 被編譯器替換成了int pn new file line int,從而呼叫我們定義的operator new,這種辦法確實很妙。需要交代的是,對於陣列同樣適用,而是在編譯的是後由編譯器計算出所需要的長度呼叫我們定義的operator new函...

C 筆記,過載new , delete 操作符

1.簡述 1 自定義過載全域性的new 和 delete,在使用new新增物件和delete物件時,會呼叫自定義全域性的new和delete操作,c 內部類也 如char,int等 不例外,同樣會呼叫自定義的new和delete。2 也可以定義作用域為當前類的new和delete,即像在類中過載其他...