C++大量的手動分配、回收內存是存在風險的,也許一個函數中一小塊內存洩漏被重復放大之後,最後掏空內存。
這裡介紹一種在debug模式下測試內存洩漏的方法。
首先在文件的開頭以確定的順序寫下這段代碼:
1 #define _CRTDBG_MAP_ALLOC 2 #include <crtdbg.h> 3 #include <stdlib.h>
第1行定義了宏,實現一些內存分配函數向debug模式的映射。
打開<crtdbg.h>我們可以找到這麼一段代碼:
可以看到,定義了_DEBUG情況下,定義_CRTDBG_MAP_ALLOC會將函數映射為_dbg的版本。
第二個步驟,對new做一個重定義
1 #define NEW_WITH_MEMORY_LEAK_CHECKING new(_NORMAL_BLOCK,__FILE__,__LINE__) 2 #define new NEW_WITH_MEMORY_LEAK_CHECKING
這裡new采用的是VC++對operator new的一個重載,可以在<vcruntime_new_debug.h>中找到,這裡不多講了。
完成以上兩步之後,程序中new和delete回收的過程便被VC++監視了,在程序退出的地方采用
1 _CrtDumpMemoryLeaks();
便可以在“輸出”窗口查看報告了。
舉個栗子
1 #define _CRTDBG_MAP_ALLOC 2 #include <stdlib.h> 3 #include <crtdbg.h> 4 #define NEW_WITH_MEMORY_LEAK_CHECKING new(_NORMAL_BLOCK,__FILE__,__LINE__) 5 #define new NEW_WITH_MEMORY_LEAK_CHECKING 6 7 int main() 8 { 9 auto p = new int[10]; 10 _CrtDumpMemoryLeaks(); 11 return 0; 12 }
這裡還有一點,VC++的編譯器cl.exe在delete之後會將內存置為0xcdcd防止再次利用,這裡顯然是程序結束時對p進行了回收。
此外,還要介紹一個new的玩法。
(尤其標准庫中很突出)C++程序使用了placement new,這裡我不是要介紹這個用法,想了解的自行。
placement new在new後邊跟了括號,這會和上面提到的VC++重載的new沖突,那麼怎麼避免,在其他地方宏定義了新的new而和placement new沖突的情況?
相信大家一定見過像下面的代碼
1 #pragma push_macro("new") 2 #undef new 3 //using the raw new 4 #pragma pop_macro("new")
#pragma push/pop_macro將宏定義名壓/彈棧,這裡現將宏new壓棧,保留原來的定義,之後取消定義,使用原生的new,使用完畢後彈棧恢復宏定義。
以上是我介紹的對new出來的內存進行洩漏檢測的簡單方法,以及延伸出的一點常用技巧。
謝謝