常见内存泄漏场景
- 对象未释放:在使用
alloc
、new
、copy
等方法创建对象后,没有调用release
或autorelease
。例如:
NSString *str = [[NSString alloc] initWithFormat:@"test"];
// 没有调用[str release]或[str autorelease]
- 循环引用:两个或多个对象相互持有对方的强引用,导致对象无法释放。比如:
@interface ClassA {
ClassB *objB;
}
@end
@interface ClassB {
ClassA *objA;
}
@end
@implementation ClassA
- (void)dealloc {
[objB release];
[super dealloc];
}
@end
@implementation ClassB
- (void)dealloc {
[objA release];
[super dealloc];
}
@end
// 使用时
ClassA *a = [[ClassA alloc] init];
ClassB *b = [[ClassB alloc] init];
a.objB = b;
b.objA = a;
[a release];
[b release];
// 由于相互持有,a和b都无法释放
- 使用
addObserver
未移除:在使用NSNotificationCenter
添加观察者后,没有在合适的时候移除观察者。例如:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"SomeNotification" object:nil];
// 没有在dealloc方法中移除观察者
// [[NSNotificationCenter defaultCenter] removeObserver:self name:@"SomeNotification" object:nil];
- C语言数组未释放:手动分配的C语言数组,未使用
free
释放。例如:
char *buffer = (char *)malloc(1024);
// 使用后没有free(buffer)
使用Leaks工具发现泄漏
- 打开Leaks工具:在Xcode中,选择
Product
-> Profile
,在弹出的Instruments
窗口中选择Leaks
模板。
- 运行应用:运行应用,让应用执行可能产生内存泄漏的操作。
- 分析结果:Leaks工具会实时检测内存泄漏,当检测到泄漏时,会在
Leaks
列表中显示泄漏对象的信息,包括对象类型、地址、引用计数等。点击泄漏对象,可以查看该对象的详细信息,如创建该对象的代码位置,通过这些信息可以定位到产生内存泄漏的代码行。
- 使用时间轴:时间轴可以显示内存使用情况的变化,通过观察时间轴上的内存增长情况,结合泄漏检测结果,更方便地分析内存泄漏出现的时机和频率,有助于排查复杂的泄漏场景。