首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

Visual C++ 記憶體洩漏偵測與定位完整指南:CRT Debug Heap、_CrtDumpMemoryLeaks、斷點追蹤

     編輯:VC 教學

C/C++ 手動記憶體管理雖靈活但極易洩漏。Visual C++ CRT Debug Heap 提供強大的內建洩漏偵測工具,零第三方依賴,本文系統介紹啟用方法、報告解讀、自動檢測、分配編號斷點定位、記憶體區塊類型區分、報告輸出重導向等完整技能。

一、 啟用偵測:必要的標頭與順序

// 必須在所有標頭之前,且順序固定
#define _CRTDBG_MAP_ALLOC       // 映射 malloc/free 到 _malloc_dbg/_free_dbg
#include 
#include              // 提供 _CrtDumpMemoryLeaks 等
  • 僅在 Debug 版本 生效 (定義 _DEBUG),Release 版仍用標準 malloc/free。
  • _CRTDBG_MAP_ALLOC 讓洩漏報告包含 檔案名與行號,極其關鍵。

二、 手動觸發洩漏報告

int main() {
    // ... 程式邏輯 ...
    _CrtDumpMemoryLeaks(); // 程式結束前呼叫
    return 0;
}

輸出至 Output 視窗 -> Debug 標籤。

三、 自動檢測:_CrtSetDbgFlag (推薦)

int main() {
    // 程式一開始設定:退出時自動呼叫 _CrtDumpMemoryLeaks
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    // ...
}

適用於多出口函數、異常退出等場景,無需在每個 return 處理。

四、 讀懂洩漏報告

Detected memory leaks!
Dumping objects ->
c:\projects\leaktest.cpp(20) : {18} normal block at 0x00780E80, 64 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
  • {18}:分配編號 (第 18 次分配)。
  • normal block:區塊類型 (見下表)。
  • 0x00780E80:位址。
  • 64 bytes:大小。
  • c:\projects\leaktest.cpp(20):分配源碼位置 (需 _CRTDBG_MAP_ALLOC)。
  • Data:前 16 字節內容 (十六進位),CD = 未初始化填充模式。

五、 記憶體區塊類型對照

六、 分配編號斷點精準定位

洩漏報告顯示 {18},表示第 18 次分配洩漏。但該行代碼可能被呼叫多次,只有第 18 次洩漏。利用 分配編號斷點 精準捕捉該次分配。

操作步驟

  1. 專案設定中斷點 (F9) 在程式進入點 (如 main 首行)。
  2. 開始偵錯 (F5),中斷於入口。
  3. 開啟 Watch 視窗,輸入:
    • 靜態連結 CRT:_crtBreakAlloc
    • 動態連結 CRT (預設 MDd):**{,,ucrtbased.dll}_crtBreakAlloc** (VS2015+) 或 {,,msvcrtd.dll}_crtBreakAlloc (舊版)
  4. 將值改為洩漏編號 (如 18)。
  5. 繼續執行 (F5),程式將在第 18 次 malloc/new 處中斷,呼叫堆疊直接顯示完整調用鏈。

七、 重導向報告輸出

// 輸出到檔案而非 Output 視窗
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); // 或 _CRTDBG_FILE_STDERR / 檔案控制代碼
// 也可用 _CRTDBG_MODE_DEBUG 輸出到偵錯器 (預設)

八、 進階:記憶體狀態檢查點


_CRT_MEM_STATE s1, s2, s3;
_CrtMemCheckpoint(&s1); // 快照 1
// ... 執行可疑代碼 ...
_CrtMemCheckpoint(&s2); // 快照 2
if (_CrtMemDifference(&s3, &s1, &s2)) {
    _CrtMemDumpStatistics(&s3); // 輸出差異統計
    _CrtMemDumpAllObjectsSince(&s1); // 傾印 s1 後所有分配物件
}

總結最佳實踐

  1. 專案 stdafx.h 頂部加入 _CRTDBG_MAP_ALLOC + crtdbg.h。
  2. CWinApp::InitInstance 首行 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);。
  3. Debug 版本每次運行自動報告洩漏。
  4. 4. 有洩漏時,用分配編號斷點精準定位源碼行與調用堆疊。 5. 修復後重測至 Object dump complete 無 Detected memory leaks。

掌握 CRT Debug Heap,記憶體洩漏不再是噩夢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型含義關注度
Normal block程式碼 malloc/new 分配★★★ 主要排查目標
Client blockMFC 物件 (如 CString, CArray) 未釋放★★ 檢查物件生命週期
CRT blockCRT 內部自用★ 通常忽略,除非 CRT 崩潰
Free block已釋放不出現在洩漏報告
Ignore block開發者標記忽略 (_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_DELAY_FREE_MEM_DF) 等)刻意排除