Day13-内存泄漏排查、僵尸对象与 MRC 回顾
一、iOS内存泄漏排查
1. 常见内存泄漏场景
- 循环引用:对象之间相互强引用(如父子对象、Block捕获self未使用weak修饰),导致无法释放516。
- 未释放Core Foundation对象:使用CF框架(如CFArrayRef、CGImageRef)时未调用CFRelease17。
- NSTimer/CADisplayLink强引用:未在适当时机调用invalidate,导致持有者无法释放516。
- 大对象未释放:如缓存图片、视频资源未及时清理416。
- ARC下的隐式泄漏:指针提前置nil,导致堆对象未被释放(如Person *p = [Person new]; p = nil;)3。
2. 排查工具与方法
- 静态分析(Analyze):通过Xcode的Product -> Analyze检测代码逻辑错误(如访问未初始化指针、未释放路径)1113。
- 动态分析(Instruments):- Leaks:检测未释放的内存泄漏,结合Call Tree定位代码位置61215。
- Allocations:监控内存分配趋势,识别异常增长区域17。
 
- Debug Memory Graph:可视化对象引用关系,快速发现循环引用613。
- 第三方工具:如腾讯的MLeaksFinder,自动化检测页面泄漏6914。
二、僵尸对象(Zombie Objects)
1. 定义与成因
- 僵尸对象:已被释放(dealloc)但仍在被访问的对象,访问时会导致EXC_BAD_ACCESS崩溃818。
- 常见场景:- 过度释放:对同一对象多次调用release(MRC下)8。
- 野指针:指针指向已释放对象后未置nil(如MRC下悬垂指针)818。
 
- 过度释放:对同一对象多次调用
2. 检测与解决
- 启用Zombie Instrument:在Instruments中选择Zombies模式,捕获访问僵尸对象的行为817。
- ARC下的防护:通过weak修饰符避免野指针,自动置nil58。
- MRC下的规范:遵循retain/release配对原则,释放后指针置nil38。
三、MRC(Manual Reference Counting)回顾
1. 核心规则
- 手动管理引用计数:通过retain增加计数,release减少计数,autorelease延迟释放17。
- 所有权原则:谁创建(alloc/new/copy)、谁释放;其他情况需显式retain79。
- Setter方法规范:需注意旧值可能已被释放的风险9。1 
 2
 3
 4- (void)setObject:(id)newObject { 
 [_object release]; // 释放旧值
 _object = [newObject retain]; // 保留新值
 }
2. 常见问题与陷阱
- 不平衡的retain/release:导致内存泄漏或过度释放17。
- 循环引用:需手动打破强引用链(如使用assign替代retain)516。
- Autorelease Pool管理:大量临时对象需手动控制释放时机,避免内存峰值9。
3. ARC的优势
- 自动化:编译器自动插入retain/release代码,减少人为错误17。
- 安全性:通过weak和strong修饰符管理所有权,避免僵尸对象57。
四、总结与建议
- 优先使用ARC:减少手动管理风险,但需注意与Core Foundation交互时的桥接(__bridge、CFRelease)17。
- 规范代码习惯:- 避免循环引用,使用weak/unowned修饰Block捕获对象5。
- 及时释放非OC对象(如C语言malloc分配的内存)17。
 
- 避免循环引用,使用
- 结合工具排查:定期使用静态分析、动态检测和内存图谱,定位复杂泄漏问题61317。
通过上述方法,开发者可有效降低内存泄漏风险,提升应用稳定性。