C++--問題27--如何檢測記憶體洩漏

大姐姐畢宿五發表於2020-10-25

C++--問題27--如何檢測記憶體洩漏


1.記憶體洩露的定義:

動態分配記憶體所開闢的空間,在使用完畢後未手動釋放,導致一直佔據該記憶體,即為記憶體洩漏。

2.造成記憶體洩漏的幾種原因:

(1)類的建構函式和解構函式中new和delete沒有配套。

(2)在釋放物件陣列時沒有使用delete[],使用了delete。

(3)沒有將基類的解構函式定義為虛擬函式,當基類指標指向子類物件時,如果基類的解構函式不是virtual,那麼子類的解構函式將不會被呼叫,子類的資源沒有正確釋放,因此造成記憶體洩露。

(4)沒有正確的清楚巢狀的物件指標。

3.在VS中檢測內從洩漏:CRT

方法一:

#define CRTDBG_MAP_ALLOC  //放在程式最前
#include <iostream>
#include <stdlib.h>    
#include <crtdbg.h> 
using namespace std;

int main()
{
	int* a = new int[10];
	int* p = new int[1000];
	_CrtDumpMemoryLeaks();  //放在程式最後
	system("pause");
	return 0;
}

點選“除錯”,然後在輸出視窗可以看到:

注意:{}中的數字指明這塊記憶體是程式中總計第幾個被申請的,這種方法沒有行號和其他資訊輸出。

要行號我們可以定義,程式碼如下:

#ifdef _DEBUG
#define New   new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

#define CRTDBG_MAP_ALLOC  
#include <stdlib.h>  
#include <crtdbg.h>  
//在入口函式中包含 _CrtDumpMemoryLeaks();  
//即可檢測到記憶體洩露

//以如下測試函式為例:
int main()
{
	char* pChars = New char[10];
	_CrtDumpMemoryLeaks();
	return 0;
}

{77}和{76}代表了第77、76次記憶體分配操作發生了洩漏,所以根據這兩個資訊,可以定位到記憶體洩漏的位置,可以新增如下程式碼:

#define CRTDBG_MAP_ALLOC
#include <iostream>
#include <stdlib.h>    
#include <crtdbg.h> 
using namespace std;

int main()
{
	_CrtSetBreakAlloc(77);
	//_CrtSetBreakAlloc(76);  //分別取消註釋即可觸發所有斷點。
	int* a = new int[10];
	int* p = new int[1000];
	_CrtDumpMemoryLeaks();
	system("pause");
	return 0;
}

在VS2019中會輸出結果如下:

你發現,程式執行到int* p = new int[1000]; 一句時,自動停下來進入除錯狀態。細細體會一下,你可以發現,這種方式你獲得的資訊遠比在程式退出時獲得檔名及行號有價值得多。因為報告洩漏檔名及行號,你獲得的只是靜態的資訊,然而_CrtSetBreakAlloc則是把整個現場恢復,你可以通過對函式呼叫棧分析(我發現很多人不習慣看函式呼叫棧,如果你屬於這種情況,強烈推薦你去補上這一課,因為它太重要了)以及其他線上除錯技巧,來分析產生記憶體洩漏的原因。通常情況下,這種分析方法可以在5分鐘內找到肇事者。

方法二:在入口函式中包含 _CrtDumpMemoryLeaks(); 

#define CRTDBG_MAP_ALLOC  
#include <stdlib.h>  
#include <crtdbg.h>  
//在入口函式中包含 _CrtDumpMemoryLeaks();  
//即可檢測到記憶體洩露

//定義函式:
inline void EnableMemLeakCheck()
{
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
}
//該函式可以放在主函式的任意位置,都能正確的觸發記憶體洩露輸出
//以如下測試函式為例:
int main()
{
	EnableMemLeakCheck();
	char* pChars = new char[10];
	//_CrtDumpMemoryLeaks();
	return 0;
}

輸出結果:

相關文章