C++--問題27--如何檢測記憶體洩漏
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;
}
輸出結果:
相關文章
- 如何檢測記憶體洩漏記憶體
- iOS檢測記憶體洩漏iOS記憶體
- JavaScript記憶體洩漏檢測工具JavaScript記憶體
- 急!請教用optimizeit檢測記憶體洩漏的問題?記憶體
- 如何在 Linux 下檢測記憶體洩漏Linux記憶體
- 使用 Instruments 檢測記憶體洩漏記憶體
- MFC 檢測記憶體洩漏的方法記憶體
- 檢測並排除記憶體洩漏 (轉)記憶體
- 如何檢測記憶體洩漏——過載new和delete記憶體delete
- ThreadLocal記憶體洩漏問題thread記憶體
- AFN的記憶體洩漏問題記憶體
- 如何解決JVM OutOfMemoryError記憶體洩漏問題?JVMError記憶體
- Node.js 應用的記憶體洩漏問題的檢測方法Node.js記憶體
- C++ 程式記憶體洩漏檢測方法C++記憶體
- C/C++記憶體洩漏及檢測C++記憶體
- VC++6.0中記憶體洩漏檢測C++記憶體
- Android檢測記憶體洩漏之leakcanaryAndroid記憶體
- iOS八種記憶體洩漏問題iOS記憶體
- iOS 11 textField記憶體洩漏問題iOS記憶體
- bea記憶體洩漏問題診斷記憶體
- HibernateDaoSupport 記憶體洩漏的問題!記憶體
- 如何檢查Javascript中的記憶體洩漏JavaScript記憶體
- iOS記憶體洩漏自動檢測工具PLeakSnifferiOS記憶體
- 記憶體洩漏問題分析之非託管資源洩漏記憶體
- 關於PHP記憶體洩漏的問題PHP記憶體
- 我是如何搞定 NodeJS 記憶體洩漏問題的NodeJS記憶體
- 請教 關於記憶體洩漏的檢測方法記憶體
- 記憶體洩漏記憶體
- 解決記憶體洩漏(1)-ApacheKylin InternalThreadLocalMap洩漏問題分析記憶體Apachethread
- 如何查詢記憶體洩漏記憶體
- 解決Instruments檢測記憶體洩漏時真機無法定位的問題記憶體
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- 【Java面試題】之記憶體洩漏Java面試題記憶體
- 使用VLD進行記憶體洩漏檢測(release + debug)記憶體
- 怎麼用弱引用實現記憶體洩漏檢測記憶體
- js記憶體洩漏JS記憶體
- Java記憶體洩漏Java記憶體
- webView 記憶體洩漏WebView記憶體