用raii机制管理资源,优先使用std::unique_ptr或std::shared_ptr替代裸指针,确保资源生命周期绑定栈对象;避免vector::push_back(new t)等手动内存管理,全局资源改用局部静态变量或智能指针配合atexit;借助addresssanitizer检测泄漏。

用 RAII 就对了,别手动 new/delete
绝大多数 C++ 内存泄漏,根源是裸指针 + 忘记 delete,或者异常路径下没释放。RAII(Resource Acquisition Is Initialization)不是概念,是必须落地的写法——资源生命周期绑定到栈对象生命周期。
- 所有动态分配,优先用
std::unique_ptr或std::shared_ptr,而不是裸int*;new出来的东西,立刻包进智能指针 - 容器(如
std::vector、std::string)自己管理内存,别再为字符串或数组手写new char[n] - 自定义类里有资源?在构造函数里获取,在析构函数里释放;确保析构函数是
noexcept(尤其含delete时)
警惕 vector::push_back(new T) 这种写法
这是新手高频泄漏点:把裸指针塞进容器,容器只拷贝指针值,不接管所有权,析构时完全不管它。
- 错误写法:
vec.push_back(new MyClass)→ 后续没人delete,泄漏铁定发生 - 正确做法:
vec.push_back(std::make_unique<myclass>())</myclass>,用std::vector<:unique_ptr>></:unique_ptr>存储 - 如果必须传裸指针给旧接口?用
ptr.release()显式移交所有权,并确认对方真会delete
全局/静态对象里 new 的东西,程序退出时不一定被 delete
全局变量的析构顺序是未定义的,若 A 的析构依赖 B,而 B 已经析构完了,delete 可能访问野指针;更糟的是,某些平台(如嵌入式或 DLL 场景)根本不会调用全局对象析构函数。
- 避免在全局作用域
new资源;改用局部静态变量 + 函数返回引用:MyClass& instance() { static MyClass obj; return obj; } - 若必须全局指针,用
std::unique_ptr并配合atexit()手动清理(仅限简单场景,慎用) - Windows DLL 中,不要在
DLL_PROCESS_ATTACH里new后指望DLL_PROCESS_DETACH里delete—— 进程终止时 detach 可能不触发
用 AddressSanitizer 编译,比靠脑子检查靠谱得多
人脑记不住所有分支和异常路径;ASan 能在运行时直接报出泄漏位置,包括哪行 new 没配对 delete,甚至泄漏大小和堆栈。
立即学习“C++免费学习笔记(深入)”;
- 编译加
-fsanitize=address -g(Clang/GCC 都支持),运行程序后看 stderr 输出 - 注意:ASan 会禁用部分优化,且不能和
-fPIE在某些旧 Android NDK 版本共存;测试环境开,发布版关 - 它不报错 ≠ 没泄漏:循环引用(
shared_ptr互相 hold)、资源未关闭(文件句柄、socket)不在 ASan 检测范围内










