为什么重载 operator new 和 operator delete 是监控内存泄漏的最直接方式
因为所有用 new 和 delete 分配/释放的堆内存,都会经过这两个函数(除非显式调用 malloc/free 或禁用全局重载)。不侵入业务代码、不依赖编译器插桩、也不需要链接额外库——只要重载它们,就能在分配时记下地址+大小+调用栈,在释放时抹除记录。最终程序退出前未被抹除的条目,就是潜在泄漏点。
注意:必须同时重载带 std::size_t 参数的 operator new 和 operator delete,以及带 noexcept 的版本(C++11 起默认加),否则某些 STL 容器或异常路径下的分配可能绕过你的监控。
如何在重载中安全记录调用栈和分配信息
仅记录 __FILE__ 和 __LINE__ 远不够——同一行多次 new 无法区分;而完整调用栈能定位到真正申请位置。推荐用 backtrace()(Linux/glibc)或 CaptureStackBackTrace()(Windows)获取帧地址,再用 backtrace_symbols() 或 SymFromAddr() 解析符号。但要注意:
-
backtrace()在信号处理函数中不安全,不要在SIGSEGV处理里调用 - 解析符号需链接
-lbfd -ldl(Linux)或初始化dbghelp.dll(Windows),且调试信息必须存在(-g编译) - 频繁调用栈采集开销大,建议只在 DEBUG 模式启用,或加运行时开关控制
示例关键片段:
立即学习“C++免费学习笔记(深入)”;