天天看點

windows 下面的記憶體洩漏排查.

記憶體洩漏排查

一下本人隻是簡單的介紹一個實用, 如果讀者很感興趣, 可以查閱msdn自己去深入調查相關的API和原理.

API 介紹

1. 馬上列印洩漏資訊:_CrtDumpMemoryLeaks();

一般用于局部跟蹤記憶體洩漏問題,使用的方法很簡單,你懷疑在某一個時刻有記憶體洩漏了,就執行這個函數調用,然後在 vs 調試器的 "output" 視窗會馬上會列印出目前所有沒有釋放的記憶體的申請明細(包括檔案名,行号, 第幾次記憶體配置設定)。

輕按兩下就可以定位到源檔案 記憶體申請的地方, 很友善.

2. 程式結束之前列印洩漏資訊:

一般用于全局的記憶體洩漏問題,在程式剛開始的時候就可以用起來。

使用方法也很簡單,執行下面兩個語句, 先初始化, 然後設定在第幾次的記憶體配置設定停住.

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

_CrtSetBreakAlloc(long); // 設定在第幾次記憶體配置設定的時候程式暫停執行,并回複現場

環境的設定

1. 每一個MFC生成的類都會有下面的語句

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#define DEBUG_NEW new(THIS_FILE, __LINE__) 

#define new DEBUG_NEW

#endif

有了這些定義列印洩漏資訊的時候就能準備的定位到檔案名和行号,輕按兩下就能定位過去。

2. 非MFC也可以利用現有的VC庫來實作這個功能,同樣是在new上面花功夫,如下:

#define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)

有了這幾行代碼,功能上面和MFC就一樣了。

3. 獲得具體導緻記憶體洩漏的那一份記憶體配置設定操作的現場。

獲得的靜态資訊裡面,在檔案名和行号後面還有一個數字,就是代表具體第幾次記憶體配置設定 (這裡是197)。

是以,我們調用_CrtSetBreakAlloc(197);程式就會在這一次記憶體配置設定的時候停下來,這樣我們就獲得了現場。

Detected memory leaks!

Dumping objects ->

d:\src-project\basictest - 副本\basictest\main.cpp(48) : {197} normal block at 0x002D9488, 128 bytes long.

 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 

Object dump complete.

樣例代碼:

#define new new(_NORMAL_BLOCK, __FILE__, __LINE__) // 友善調試輸出檔案行号資訊

void MemoryTest() {

    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); // 全局設定, 程式退出的時候可以看見記憶體洩漏.

    _CrtSetBreakAlloc(55); // 第55次記憶體配置設定的時候停止.

    int *p = new int(10); // 配置設定記憶體

    _CrtDumpMemoryLeaks(); // 檢查目前有哪些記憶體沒有釋放.

}