VS2005內存泄露檢查

 

內存泄露的含義是:拿走了一塊“堆”內存塊,在某檢查點處,發現沒有歸還這個內存塊。 如果是: 地址A = malloc(N); 因爲沒有調用free(地址A),所以內存泄露了。

如果是: 地址B = new 類型T; 因爲沒有調用delete 地址B,所以內存泄露了。

如果是:從用戶的內存池中取一個內存塊,沒有調用相應的歸還給內存池的操作,也認爲是“內存泄露”。

從哪裏拿了一個東西,要歸還到那個地方去。例如:從圖書館L中借了本書,歸還給圖書館B,肯定要捱罵的。

同理,從圖書館L中借了本小說,卻還給圖書館一本雜誌,也是要捱罵的。 函數_CrtDumpMemoryLeaks()功能:檢查內存泄露並且在VC的輸出窗口打印出泄露的內存塊信息。

例子1 :

#include

#include

 

int main()

{ int* x = new int();

_CrtDumpMemoryLeaks()

}

輸出:

Detected memory leaks!

Dumping objects -> {61} normal block at 0x00382650, 4 bytes long. Data: < > 00 00 00 00

非常好,發現了int* x對應的內存塊泄露了

 

例子2 :

template struct Test

{ Test()

{m_p = new char[Size];

}

~Test()

{ delete[] m_p;}

char* m_p;

};

Test<123> t;

int main()

{ int* x = new int()

; _CrtDumpMemoryLeaks() ;

}

輸出:

Detected memory leaks!

{62} normal block at 0x00382708, 4 bytes long.

{61} normal block at 0x00382650, 123 bytes long.

非常不好,它把全局變量t也報告了。這是一個嚴重的誤報。

原因是在_CrtDumpMemoryLeaks()調用時, 全局變量t還沒有離開生存期呢,所以此時~Test()未調用呢,delete[] m_p還沒調用呢。

 

例子3 :

Test<123> t;

int main()

{ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

int* x = new int();

}

輸出:

Detected memory leaks!

{62} normal block at 0x00382708, 4 bytes long.

非常好,通過_CrtSetDbgFlag函數,告知Crt庫在程序完全退出時,打印一下內存泄露的情況。

這時,全局變量t已經析構了,所以誤報沒有了。

 

例子4 :

#include

using namespace std;

#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

#define new DEBUG_NEW

int main()

{ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

int* x = new int();

}

輸出:

Detected memory leaks!

c:/sdfdfsdf/sdfdfsdf.cpp(14) :

{61} normal block at 0x00382650, 4 bytes long.

太酷了!居然在調試的輸出窗口中,顯示了造成內存泄露的代碼位置。

雙擊一下,還能自動跳到文本編輯器 中對應的代碼行上。

 

例子5 :

#include int main()

{ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

std::cout<<"hello world"<

 

調用堆棧窗口。 看到一些函數的調用關係,順着點點看看,居然發現了int* x = new int;這一行。

這個62是怎麼知道的呢?原來在內存泄露的輸出信息裏,

如下所示:

Detected memory leaks!

{62} normal block at 0x00382708, 4 bytes long.

大括號中62就是第62次分配內存時,這塊內存泄露了。通過_CrtSetBreakAlloc調用,告知Crt庫,在 第62次分配內存的調用時,

自動暫停程序,讓程序員檢查函數調用棧。 如何保證下次程序運行時,

第62此分配內存的調用就是int* x = new int;這句造成的呢?

答案是不能。

如果程序沒有複雜的時序相關的邏輯(多線程),輸入的值是一定的,則程序每次運行的行爲是一定的。

 

例子8 :

class Init_before_main

{

public: Init_before_main()

{ _CrtSetBreakAlloc(62);

}

};

Init_before_main g_tmp;

int main()

{ int* x = new int;

return 0;

}

這是對例子7的一點改進,保證在int* x = new int;調用之前,調_CrtSetBreakAlloc(62);。

否則,如下的調用順序可能會漏過了第62次分配調用 int* x = new int; _CrtSetBreakAlloc(62);

如何自己實現內存泄露檢查工具呢?思路很簡單,重載new,delete運算符,使用自己宏替換malloc和free。

所有的分配和釋放動作必須經過我過手,我才能加入點私貨(統計信息等)。這樣就可以檢查內存泄露了。

發佈了14 篇原創文章 · 獲贊 14 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章