在項目預編譯頭 stdafx.h 最頂部添加(順序不可變):
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
_CRTDBG_MAP_ALLOC 將 malloc/free 映射到調試版 _malloc_dbg/_free_dbg,記錄文件/行號。僅 Debug 構建生效 (_DEBUG 定義時)。
在程序退出點調用:
_CrtDumpMemoryLeaks();
或在程序入口設置標志(自動在退出時調用):
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
Detected memory leaks!
Dumping objects ->
C:\Project\test.cpp(15) : {45} normal block at 0x00441BA0, 2 bytes long.
Data: <AB> 41 42
{45}:分配序號(程序啟動以來第 45 次分配)。normal block:塊類型——normal(用戶代碼), client(MFC 對象), CRT(運行庫內部)。at 0x...:內存地址。2 bytes long:大小。Data: ...:前 16 字節十六進制內容。_CRTDBG_MAP_ALLOC 時顯示文件名與行號 (test.cpp(15)),雙擊可直接跳轉源碼。在監視窗口輸入:
_crtBreakAlloc // 單獨 CRT 靜態庫
{,,msvcrtd.dll}_crtBreakAlloc // 使用 CRT 動態庫 (/MDd)
將值改為洩漏報告中的序號 (如 45)。程序運行到第 45 次分配自動中斷,查看調用堆棧確定具體業務邏輯與條件。
或在代碼中硬編碼:_crtBreakAlloc = 45; / _CrtSetBreakAlloc(45);。
適用於定位某代碼段洩漏:
_CrtMemState s1, s2, s3;
_CrtMemCheckpoint(&s1); // 快照 1
// ... 疑似洩漏代碼 ...
_CrtMemCheckpoint(&s2); // 快照 2
if (_CrtMemDifference(&s3, &s1, &s2)) {
_CrtMemDumpStatistics(&s3); // 輸出差異統計
}
輸出示例:
75 bytes in 3 Normal Blocks. 5037 bytes in 41 CRT Blocks. Largest number used: 5308 bytes. Total allocations: 7559 bytes.
若 Normal Blocks 增長且未釋放,即為洩漏。可二分法縮小範圍定位具體函數。
| 類型 | 來源 | 是否出現在洩漏報告 |
|---|---|---|
| Normal | 用戶 new/malloc | 是 |
| Client | MFC new (帶析構對象) | 是 |
| CRT | 運行庫內部 | 極少 (除非 CRT 崩潰) |
| Free | 已釋放塊 | 否 |
| Ignore | 用戶標記忽略 (_CrtSetDbgFlag) | 否 |
默認輸出到「輸出」視窗 Debug 頁。若被其他庫劫持,可恢復:
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
CRT 調試堆提供了零成本、無需第三方工具的強大洩漏檢測能力。結合 _CrtDumpMemoryLeaks、分配序號斷點、內存狀態差異比較,可高效定位 99% 的內存洩漏問題。MFC 項目同樣適用。