時間總是能讓一切改變,至上次發blog我已經不在福州。現在就職于成都一家公司,剛來一直在閱讀代碼,發現服務器的邏輯代碼,有挺多讓直接new申請內存,對這個我總覺得有些裸奔的感覺。啊哈,有可能被同事看到,我沒有其他意思哈,只是覺得沒有管理,一不小心就內存泄露了,寫的時候要小心又小心。如果要從堆中獲取一塊內存,一般還是交給智能指針去管理更妥些。
以上這大段和下面寫的都沒有任何關系。嗯,是的,確實是沒有關系,我只是在思考已經這樣寫了,能不能對內存申請和釋放做個監控。其實網上代碼一堆,我也自己按照自己的思路實現了一下,原理都是重載new和delete方式了。閑言少敘,話不多說。
同樣,我也要重載new與delete關鍵字,但是我重載的是帶3參數的,具體的申請交給我的CMemLeakMonitorMgr管理器吧。以后再具體說明,先看如下代碼:
void* operator new(size_t size, const char* funName, size_t line)
{
return g_pMemLeakMonitorMgr.Alloc(funName,line,size);
}
void* operator new[](size_t size, const char* file, int line)
{
return operator new(size, file, line);
}
void* operator new(size_t size)
{
return malloc(size);
}
void* operator new[](size_t size)
{
return malloc(size);
}
void* operator new(size_t size, const std::nothrow_t&) throw()
{
return ::operator new(size);
}
void* operator new[](size_t size, const std::nothrow_t&) throw()
{
return ::operator new[](size);
}
void operator delete(void* p)
{
return g_pMemLeakMonitorMgr.Free(p);
}
然后我定義以下宏,來替換new操作,請看下面:
#define DEBUG
#ifdef DEBUG
#define DEBUG_NEW new(__FUNCTION__, __LINE__)
#define DEBUG_DELETE(p) delete p
#else
#define DEBUG_NEW new
#define DEBUG_DELETE(p) delete p
#endif
上面的宏應該不用多說吧,設計的是只有在debug情況下,才會生效。這里用DEBUG_NEW與DEBUG_DELETE宏來申請和釋放內存,其實完全可以直接替換new與delete,但是我不想這么做,因為我想在使用者用該宏時明白它做了一些“見不得人”的事情。哈,
還是那句話閑言少敘,廢話不能多。看下怎么使用吧:
void fun1()
{
DEBUG_NEW int;
}
void fun2()
{
char *p = DEBUG_NEW char;
DEBUG_DELETE(p);
}
void fun3()
{
DEBUG_NEW int;
}
int main()
{
Test2 *p = DEBUG_NEW Test2();
DEBUG_DELETE(p);
fun1();
fun2();
fun3();
fun1();
fun1();
g_pMemLeakMonitorMgr.ReportMemLeak();
return 0;
}
嗯,是的,這個很好懂,通過宏來替換之前的new和delete,然后幾個函數中有些函數是有內存泄露的。然后通過ReportMemLeak來報告結果。可以顯示的如下:
Test2 constructor.
Test2 destructor.
Test2 constructor.
Test2 destructor.
Memory leak FunName:fun1,line:182,totalsize:12 bytes.
Memory leak FunName:fun3,line:194,totalsize:4 bytes.