面试题答案
一键面试常见因内存管理引发崩溃的场景及容错机制
- 过度释放对象
- 问题:过度释放对象会导致程序访问已释放的内存,引发“野指针”错误,造成程序崩溃。例如,对一个已经释放的对象再次发送
release
消息。 - 防护:使用自动释放池(
@autoreleasepool
),在合适的代码块结束时自动释放对象,避免手动过度释放。同时,可以使用安全释放宏,如#define SAFE_RELEASE(x) { [x release]; x = nil; }
,这样在释放对象后将指针置为nil
,避免野指针。
- 问题:过度释放对象会导致程序访问已释放的内存,引发“野指针”错误,造成程序崩溃。例如,对一个已经释放的对象再次发送
- 内存泄漏
- 问题:如果对象没有被正确释放,会导致内存不断被占用,最终耗尽系统内存,使应用崩溃。比如在一个循环中不断创建对象但未释放。
- 防护:在对象的
dealloc
方法中确保正确释放所有引用的对象。使用ARC(自动引用计数),ARC会自动管理对象的内存释放,减少手动管理带来的泄漏风险。若不能使用ARC,在对象生命周期结束时,仔细检查并释放所有持有对象的实例变量。
- 悬空指针(Dangling Pointer)
- 问题:当一个对象被释放,但指向它的指针没有被更新时,就会产生悬空指针。如果后续使用这个指针访问对象,就会导致崩溃。例如,对象A持有对象B的指针,对象B被释放后,对象A的指针没有更新。
- 防护:当对象被释放时,将指向它的所有指针置为
nil
。可以通过在对象的dealloc
方法中,通知所有持有该对象指针的其他对象,让它们将指针置为nil
。或者在访问指针前,先检查指针是否为nil
,如if (myObject) { // 使用myObject }
。
- 数组或集合中的对象释放问题
- 问题:向数组或集合中添加对象后,如果在数组或集合还存在时,提前释放了数组中的对象,当访问数组中的对象时会引发崩溃。
- 防护:当向数组或集合添加对象时,确保对象的所有权被正确管理。若使用手动内存管理,数组或集合会对添加的对象进行
retain
操作,在移除对象时,要进行release
操作。使用ARC时,ARC会自动处理这些操作。同时,在遍历数组或集合时,避免在遍历过程中直接释放正在访问的对象,可以先将需要释放的对象收集起来,遍历结束后再进行释放。