内存泄漏排查聚焦三类高危模式:一是动态内存未配对释放,需检查所有执行路径的new/malloc与delete/free严格匹配;二是shared_ptr循环引用,须用weak_ptr打破;三是异常路径绕过清理,应优先采用raii或智能指针保障析构释放。

查 new/malloc 和 delete/free 是否严格配对
这是最基础也最容易漏掉的一环。不能只看有没有 free,要看所有执行路径是否都覆盖到了。
- 函数有多个 return 语句?每个 return 前都要确认资源已释放,或改用 RAII 封装
- 用了 if/else 或 switch?各分支里分配的内存,必须在各自出口前释放
- 指针被重新赋值前,是否先 free 了旧地址?比如
ptr = malloc(...); ptr = malloc(...);就丢了第一次的地址
查 shared_ptr 是否形成循环引用
C++ 中 shared_ptr 自动管理生命周期,但一旦 A 持有 B 的 shared_ptr,B 又持有 A 的,两者 refcount 永远不为 0,内存就永远不释放。
- 检查类成员是否互相用 shared_ptr 指向对方(尤其是树、链表、观察者等结构)
- 看到
std::shared_ptr<someclass></someclass>出现在双向关联字段中,立刻警惕 - 用
std::weak_ptr替换其中一端引用,就能打破循环——这不是妥协,是设计必需
查异常发生时的资源清理是否可靠
代码走 try-catch 很常见,但很多开发者只在 catch 里处理错误,忘了分配后的内存可能根本没机会走到 catch 外面的 delete。
- new 后紧跟 throw,delete 写在后面?那 delete 永远不会执行
- 推荐统一用智能指针或 RAII 类(如自定义 Buffer 类,在构造时 malloc,析构时 free)
- 如果必须裸指针 + 手动管理,就把分配和释放包进同一个作用域,靠作用域自动析构兜底
查静态/全局容器是否无限制累积
Java 或 C++ 里,static Map、全局 list、缓存队列,很容易变成“只进不出”的内存黑洞。
- 看有没有清除机制:定时清理、LRU 驱逐、使用后 remove、容量上限控制
- 特别注意监听器注册后是否配套注销,内部类是否隐式持有了 Activity/Context 引用
- 日志、调试信息写入全局集合?上线前务必删掉或加开关控制











