_CrtDumpMemoryLeaks() 是 Windows 下最轻量的泄漏检测方式,仅需在 main 开头调用 _CrtSetDbgFlag 并启用调试堆,程序退出时自动报告未释放内存,但无调用栈且依赖正常返回。
_CrtDumpMemoryLeaks() 在 Windows 下快速捕获泄漏Windows 平台下最轻量、无需额外工具的泄漏检测方式,依赖 MSVC 的 CRT 调试堆。它只在程序退出时打印未释放的堆块摘要,不提供调用栈,但胜在开箱即用。
关键点:
main())开头调用 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
/MDd 或 /MTd),且定义了 _DEBUG
#include 前定义 _CRTDBG_MAP_ALLOC
exit() 或异常终止),泄漏可能不被触发——需确保正常返回到 main 末尾#define _CRTDBG_MAP_ALLOC #include#include int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); int* p = new int[100]; // 忘记 delete[] p; return 0; // 此处触发检查 }
valgrind --leak-check=full 定位源头valgrind 是跨平台事实标准,但仅适用于 Linux/macOS(macOS Catalina+ 需注意系统限制)。它能精确指出每一块泄漏内存的分配位置,包括函数名、源码行、调用栈。
常见误操作:
-g 编译,导致报告里只有地址没有符号——务必加 g++ -g -O0
--track-origins=yes:对“未初始化值”间接导致的泄漏排查很有用--leak-check=summary 够用:它只报总数,漏掉具体泄漏点new 分配后未匹配 delete,valgrind 会如实报告g++ -g -O0 leak.cpp -o leak valgrind --leak-check=full --show-leak-kinds=all ./leak
AddressSanitizer(ASan)在编译期注入运行时检查Clang/GCC 支持的 ASan 不仅查内存泄漏,还查越界、UAF、栈使用后释放等。相比 valgrind,它更快(约 2× 慢),且支持多线程,适合 CI 或日常开发启用。
启用方式简单,但有几个硬性前提:
-fsanitize=address
valgrind 共存(二者都劫持 malloc/free)-fsanitize=address -fno-omit-frame-pointer -g 并设置环境变量 ASAN_OPTIONS=detect_leaks=1
std::string 的 SSO 优化)可能触发误报,可加 detect_stack_use_after_return=1 细化控制g++ -fsanitize=address -fno-omit-frame-pointer -g leak.cpp -o leak ASAN_OPTIONS=detect_leaks=1 ./leak
RAII 是 C++ 抗泄漏的核心机制,但真实项目中仍有三类典型漏点:
s
td::shared_ptr 循环引用:两个对象互相持有对方的 shared_ptr,引用计数永不归零——改用 std::weak_ptr 打破循环new 出的指针,调用方忘记包装成 unique_ptr
dlopen 加载的插件未调用对应 dlclose,ASan 和 valgrind 能发现,但无法直接修复真正难排查的,往往不是 new 没配 delete,而是资源生命周期跨越模块边界、析构时机不可控、或工具链本身对某些分配模式(如 mmap、自定义 allocator)无感知。