介紹:
動態分配、回收內存是C/C++編程語言一個最強的特點,但是中國哲學家孫(Sun Tzu,我不知道是誰?那位知道?) 指出,最強的同時也是最弱的。這句話對C/C++應用來說非常正確,在內存處理出錯的地方通常就是BUGS產生的地方。一個最敏感和難檢測的BUG就是內存泄漏-沒有把前邊分配的內存成功釋放,一個小的內存泄漏可能不需要太注意,但是程序泄漏大塊內存,或者漸增式的泄漏內存可能引起的現象是:先是性能低下,再就是引起復雜的內存耗盡錯誤。最壞的是,一個內存泄漏程序可能用完了如此多的內存以至於引起其他的程序出錯,留給用戶的是不能知道錯誤到底來自哪裏。另外,一個看上去無害的內存泄漏可能是另一個問題的先兆。幸運的是VC++DEBUGER和CRT庫提供了一組有效的檢測和定位內存泄漏的工具。本文描述如何使用這些工具有效和系統的排除內存泄漏。
_CrtDumpMemoryLeaks()就是檢測從程序開始到執行該函數進程的堆使用情況,通過使用_CrtDumpMemoryLeaks()我們可以進行簡單的內存泄露檢測。
啓用內存泄露檢測:
檢測內存泄漏的主要工具是調試器和 C 運行時庫 (CRT) 調試堆函數。若要啓用調試堆函數,請在程序中包括以下語句:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
注意:
#include必須按照以上所示順序。如果更改了順序,所使用的函數可能無法使用。
通過包括crtdbg.h,將 malloc 和 free 函數映射到其“Debug”版本 _malloc_dbg 和_free_dbg,這些函數將跟蹤內存分配和釋放。此映射只在調試版本(在其中定義了 _DEBUG)中發生。發佈版本使用普通的 malloc 和 free 函數。
#define 語句將 CRT 堆函數的基版本映射到對應的“Debug”版本。並非絕對需要該語句,但如果沒有該語句,內存泄漏轉儲包含的有用信息將較少。
在添加了上面所示語句之後,可以通過在程序中包括以下語句來轉儲內存泄漏信息:
_CrtDumpMemoryLeaks()
使用示範:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define new new( _CLIENT_BLOCK, __FILE__, __LINE__)
int main()
{
int* leak = new int[10];
_CrtDumpMemoryLeaks();
}
這個示範程序與前面講的多了一個宏定義:
#define new new( _CLIENT_BLOCK, __FILE__, __LINE__)
原因稍後再說,我們先看看程序運行(提醒:不要按Ctrl+F5,按F5)後的結果。
程序調試後在“輸出”窗口輸出如下:
Detected memory leaks!
Dumping objects ->
e:workmyprojecttesttesttest.cpp(57) : {48} client block at 0x00392BB0, subtype 0, 40 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
“輸出”很明顯的告訴了你在test.cpp文件的第57行分配了一個40字節的內存而沒有釋放。在“輸出”窗口中選擇包含文件名和行號的行,然後按 F4 鍵即可進入到源文件中分配內存的行。
現在我們再來看看如果不加之前那個new的宏定義會出現怎麼樣的結果。
程序調試後在“輸出”窗口輸出如下:
Detected memory leaks!
Dumping objects ->
{48} normal block at 0x00392BB0, 40 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
與之前的對比,這次的輸出並沒有告訴我們這個內存泄露具體是在哪個位置引起的。另外如果沒定義
#define _CRTDBG_MAP_ALLOC
也會引起同樣的結果