一般來說,當一個應用進程存在存在記憶體流失的時候,可採用微軟推薦的標準方法來進行檢查。
當然,這個方法只適用於運行期庫的標準堆,進程建立的私人堆不能用此方法來檢測,這種情況我們暫時不考慮。
先大概說一下微軟推薦的檢測方法。
檢測記憶體流失的主要工具是調試器和 C 執行階段程式庫 (CRT) 調試堆函數。若要啟用調試堆函數,請在程式中包括以下語句:
#define _CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>
通過包括 crtdbg.h,將 malloc 和 free 函數映射到其“Debug”版本 _malloc_dbg 和 _free_dbg,這些函數將跟蹤記憶體配置和釋放。此映射只在調試版本(在其中定義了 _DEBUG)中發生。發布版本使用普通的 malloc 和 free 函數。
#define 語句將 CRT 堆函數的基版本映射到對應的“Debug”版本。並非絕對需要該語句,但如果沒有該語句,記憶體流失轉儲包含的有用資訊將較少。
在添加了上面所示語句之後,可以通過在程式中包括以下語句來轉儲記憶體流失資訊:
_CrtDumpMemoryLeaks();
這樣,在調試輸出區就能看到堆泄漏檢測的內容了,而且裡面還包含了原始碼資訊,極大的方便了調試工作。
微軟又提到:
如果程式總是在同一位置退出,調用 _CrtDumpMemoryLeaks 將非常容易。如果程式從多個位置退出,則無需在每個可能退出的位置放置對 _CrtDumpMemoryLeaks 的調用,而可以在程式開始處包含以下調用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
這樣,只有在入口函數退出之後,運行期庫進行最後的清理工作結束之前,_CrtDumpMemoryLeaks才會被真正調用,你將有機會把自己建立的全域對象所佔用的記憶體釋放掉,避免這些記憶體被統計到未釋放的堆當中。
需要注意的是,前面的標頭檔包含應該被原始碼中的每個模組所引用,未引用的模組的堆資訊在輸出的時候將無法被識別,所以你最好將這個標頭檔包含放在類似afxstd.h的預包含檔案中,以保證所有模組都能引用到這組標頭檔資訊。
另外 ,可以把輸出資訊重新導向到比如磁碟的檔案中,方法是調用這個函數:_CrtSetReportMode。
現在再介紹在實際應用中發現的問題,上面的步驟可以解決你自己的程式的堆泄漏問題,但如果你的可執行程式引用了其他庫,靜態或者是動態,如果這些庫中也存在堆泄漏,那麼你是看不到原始碼資訊的,只能看到原始資訊!
下面只說靜態庫且有原始碼的情況,這時候,你可以在這個靜態庫的原始碼的每個模組中加入上面提到的語句:
#define _CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>
這樣,你在調試輸出中就能看到原始碼資訊了,至於動態庫的問題在後續中再分析。