必须定义 _CRTDBG_MAP_ALLOC 并在 main() 开头调用 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF),否则 _CrtDumpMemoryLeaks() 仅显示 {123} 分配编号而无文件行号。

Visual Studio 自带的 CRT 调试堆功能在 Debug 模式下就能直接定位 C++ 内存泄漏,不需要装插件、不依赖第三方工具——但必须配对启用宏定义和标志位,否则报告里只有 {123} 编号,看不到文件行号。
为什么 _CrtDumpMemoryLeaks() 只显示 {123} 却不报文件名?
默认情况下,CRT 不记录分配位置。要让泄漏报告带上源码路径和行号,得提前做两件事:
-
#define _CRTDBG_MAP_ALLOC必须放在#include <crtdbg.h>之前,否则new和malloc不会映射到带调试信息的版本 - 必须在
main()开头(不是末尾)调用_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF),漏掉_CRTDBG_LEAK_CHECK_DF就不会触发退出检查 - 如果用了自定义
operator new,但没重载operator new(size_t, void*)(placement new),STL 内部分配(如std::vector扩容)会绕过你的监控,导致 CRT 报泄漏而你统计为 0
如何用 {123} 定位到具体 new 那一行?
拿到泄漏编号后,不能靠猜或扫代码——直接让调试器在第 N 次分配时中断:
- 在
main()开头插入_CrtSetBreakAlloc(123);(把 123 换成实际编号) - F5 启动,程序会在第 123 次调用
malloc或new时自动断下 - 看调用栈(Call Stack 窗口),顶层是你自己的代码行,不是 CRT 或 STL 内部帧
- 记得删掉
_CrtSetBreakAlloc再提交代码,否则用户运行会直接崩
VLD 2.5.1 在 VS2022 上还能用吗?
能,而且比 CRT 更省事:它自动记录完整调用栈,连 ucrtbased.dll!malloc 这种底层调用都能回溯到你写的 LineProApi.cpp(1975)。但要注意几个硬限制:
立即学习“C++免费学习笔记(深入)”;
- 只在 Debug 配置生效,Release 下无输出
- 需在项目属性 → C/C++ → 预处理器 → 预处理器定义中添加
VLD_FORCE_ENABLE - 链接器 → 输入 → 附加依赖项加
vld.lib,同时把vld.dll放到可执行文件同目录(否则运行时报找不到 DLL) - VLD 官方插件不支持 VS2022,但命令行和控制台报告完全可用,图形界面只是锦上添花
真正难搞的泄漏,往往卡在 CRT 和自定义分配器的边界上——比如重载了 operator new 却漏了 placement 版本,或者 ASan 检测不到全局 POD 数组;这些地方不打日志、不看调用栈、不设断点,光盯报告根本发现不了。


















