下面介紹用過載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,即像在類中過載其他...