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記憶體
- 如何在 Linux 下檢測記憶體洩漏Linux記憶體
- ThreadLocal記憶體洩漏問題thread記憶體
- redisson記憶體洩漏問題排查Redis記憶體
- 如何解決JVM OutOfMemoryError記憶體洩漏問題?JVMError記憶體
- Node.js 應用的記憶體洩漏問題的檢測方法Node.js記憶體
- 解決記憶體洩漏(1)-ApacheKylin InternalThreadLocalMap洩漏問題分析記憶體Apachethread
- 如何檢查Javascript中的記憶體洩漏JavaScript記憶體
- Android記憶體洩漏檢測與修復技巧Android記憶體
- 記憶體洩漏問題分析之非託管資源洩漏記憶體
- BufferedImage記憶體洩漏和溢位問題記憶體
- 關於PHP記憶體洩漏的問題PHP記憶體
- 解決Instruments檢測記憶體洩漏時真機無法定位的問題記憶體
- 使用VLD進行記憶體洩漏檢測(release + debug)記憶體
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- js記憶體洩漏JS記憶體
- Android記憶體洩漏Android記憶體
- Android 記憶體洩漏Android記憶體
- jvm 記憶體洩漏JVM記憶體
- Java記憶體洩漏Java記憶體
- 分析ThreadLocal的弱引用與記憶體洩漏問題thread記憶體
- 記憶體洩漏引起的 資料庫效能問題記憶體資料庫
- 對於記憶體洩漏問題的簡單認知記憶體
- 如何避免JavaScript中的記憶體洩漏?JavaScript記憶體
- 記憶體洩漏的原因記憶體
- valgrind 記憶體洩漏分析記憶體
- Android 記憶體洩漏檢測工具 LeakCanary(Kotlin版)的實現原理Android記憶體Kotlin
- 【記憶體洩漏和記憶體溢位】JavaScript之深入淺出理解記憶體洩漏和記憶體溢位記憶體溢位JavaScript
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- 使用 Chrome Dev tools 分析應用的記憶體洩漏問題Chromedev記憶體
- MAT工具定位分析Java堆記憶體洩漏問題方法Java記憶體
- 軟體測試學習教程——過載new或delete來檢測記憶體洩漏delete記憶體
- 阿里二面:談談ThreadLocal的記憶體洩漏問題?問麻了。。。。阿里thread記憶體
- 這可能是,Flutter 中最“強悍”的記憶體洩漏檢測方案......Flutter記憶體
- Android記憶體洩漏場景Android記憶體
- PHP 記憶體洩漏分析定位PHP記憶體
- 記憶體洩漏除錯工具記憶體除錯
- ThreadLocal真會記憶體洩漏?thread記憶體