行與不行,就憑我這水平,說出來未免顯示太過自大。不還,我還想根據本身的代碼來討論這個問題。ios
重載operator new來檢測內存只的辦法,那就是在new的時候記錄指針地址及文件名、行號,在delete的時候取消記錄。到最後程序結束,還有哪些指針未釋放,則爲泄漏。數組
第一步,你得重載operator new,或者也能夠重寫。在http://www.cplusplus.com/reference/new/operator%20new/中指明new有三種形式,由於咱們還分配數組,故還有new[]這個函數也要重載。那麼有6種。原文中指明「The allocating versions ((1) and (2)) are also replaceable:」,則說明咱們只能重載4個函數(也必須,否則檢測不到部份內存分配,沒有意義)。因爲placement new不會有內存泄漏,也不能重載,能夠無論。ide
#include <iostream> #include <cstdlib> using namespace std; inline void *operator new[](std::size_t size, const char *file, int line) { std::cout << "memory allocate at " << file << " line " << line << std::endl; void *p = ::operator new(size);// operator new (size,std::nothrow) return p; } inline void * operator new(std::size_t size, const char *file, int line) { std::cout << "memory allocate at " << file << " line " << line << std::endl; void *p = ::operator new(size); return p; } inline void operator delete(void *p) { std::cout << "free" << std::endl; free(p); } inline void operator delete[] (void *p) { std::cout << "free[]" << std::endl; free(p); } #define new new(__FILE__, __LINE__) class TTest { public: TTest(){ std::cout << "construct...." << std::endl; } ~TTest(){ std::cout << "destruct...." << std::endl; } }; int main() { TTest *p = new TTest(); delete p; return 0; }
注意上面的代碼中,由於懶,並無重載完4個函數。另外,注意new函數是重載,故能夠調用::operator new,而delete函數是重寫,再調::operator delete就遞歸成死循環了。不過這並不影響我說明問題。函數
結果:spa
memory allocate at ../test/main.cpp line 61 construct.... destruct.... free 按 <RETURN> 來關閉窗口...
看,已經知道分配的文件、行號,還能知道是否已分配,那麼說明仍是可行的。指針
但是,並非全部的程序都是這麼簡單的。重載後,咱們固然但願所來new的用法及參數都不用變。由於咱們不但願已寫的代碼須要修改。從另外一個方面說,若是用了第三方庫,總不能一個個將別人的new替換成本身的函數。因而有了「#define new new(__FILE__, __LINE__)」這行代碼,經過一個宏定義巧妙地將函數替換了。code
new int()被替換成new(__FUNCTION__,__LINE__) int(),這樣,原來的代碼不變。可是,這個宏定義並不夠巧妙。上面提到,new有三種形式,這個宏定義只能替換最經常使用的一種void* operator new (std::size_t size) throw (std::bad_alloc);對於其餘則無能爲力。blog
#include <iostream> #include <cstdlib> using namespace std; inline void *operator new[](std::size_t size, const char *file, int line) { std::cout << "memory allocate at " << file << " line " << line << std::endl; void *p = ::operator new(size);// operator new (size,std::nothrow) return p; } inline void * operator new(std::size_t size, const char *file, int line) { std::cout << "memory allocate at " << file << " line " << line << std::endl; void *p = ::operator new(size); return p; } inline void operator delete(void *p) { std::cout << "free" << std::endl; free(p); } inline void operator delete[] (void *p) { std::cout << "free[]" << std::endl; free(p); } #define new new(__FILE__, __LINE__) class TTest { public: TTest(){ std::cout << "construct...." << std::endl; } ~TTest(){ std::cout << "destruct...." << std::endl; } }; int main() { char *buff[10240] = {'\0'}; TTest *p = new TTest(); delete p; p = new(buff) TTest(); return 0; }
顯然,p = new(buff) TTest();調用了第三種new函數void* operator new (std::size_t size, void* ptr) throw();因爲參數問題編譯報錯。其實,第2、三種new函數原型在STL、BOOST裏很經常使用。因此這種替換並不適用。遞歸
因爲我並不知道編譯器#define new new(__FILE__, __LINE__)是怎麼去解釋這行代碼的,故無法寫出一個實現三種函數原型都能替換的宏定義。固然,若是你只想知道有沒有內存泄漏,不須要知道文件名、行號,則重寫new函數而不是重載是可行的。但感受這也太雞肋了。內存
不知道有沒有大神能實現函數的替換,望指教。