面试题答案
一键面试自动释放池的合理使用场景及原理
- 原理:
自动释放池(Autorelease Pool)是一种内存管理机制。当一个对象发送
autorelease
消息时,该对象会被放入最近的自动释放池中。自动释放池在被销毁时,会向池中的所有对象发送release
消息,减少对象的引用计数。如果对象的引用计数变为0,对象就会被销毁并释放占用的内存。 - 合理使用场景:
- 大量临时对象创建:例如在循环中创建大量临时对象时,如果不及时释放,可能导致内存峰值过高。如处理图像数据,每次处理一帧图像会创建很多临时的图像数据对象,将这些对象创建在自动释放池块内,当循环结束自动释放池销毁,这些对象会被及时释放,降低内存峰值。
- 在非主线程中:非主线程默认没有自动释放池,若在非主线程中有较多对象创建,手动创建自动释放池能避免内存泄露。例如在一个执行长时间任务的子线程中,若不创建自动释放池,任务执行过程中创建的对象会一直占用内存,直到线程结束,手动创建则能及时释放。
ARC机制下仍可能出现的内存问题及排查方法
- 内存问题:
- 循环引用:两个或多个对象之间相互持有对方的强引用,导致对象的引用计数永远不会变为0,无法被释放。例如,一个视图控制器A持有一个自定义视图B,而视图B又持有视图控制器A,就形成了循环引用。
- NSTimer引起的内存泄露:如果NSTimer以target - action方式创建,且target为self(通常是视图控制器),而NSTimer被添加到RunLoop中,若在视图控制器销毁时没有停止NSTimer,NSTimer会一直持有视图控制器,导致视图控制器无法释放。
- 排查方法:
- 使用 Instruments工具:
- Leaks工具:可检测应用程序中的内存泄露。运行应用程序时,Leaks工具会标记出未释放的内存块,并尝试关联到产生泄露的代码位置。
- Allocation工具:能监控对象的创建和销毁情况。通过观察对象的生命周期,判断对象是否在预期的时间被释放,若对象数量持续增加且未减少,可能存在内存问题。
- 代码审查:
仔细检查对象之间的引用关系,特别是属性的修饰符(如
strong
、weak
等)。对于可能出现循环引用的地方,如两个对象相互引用,确保至少一方使用weak
或unowned
修饰符来打破循环。对于NSTimer,确保在不需要时及时调用invalidate
方法停止它,并将其置为nil
。
- 使用 Instruments工具: