写项目过程中经常遇到一些空指针或者僵尸对象问题,类似访问了野指针,比如对一个已经释放的对象执行了release、访问已经释放对象的成员变量或者发消息。
即会出现BAD_ACCESS错误,以下办法来帮助我们快速定位找到错误位置并及时修复:
1. 重写object的respondsToSelector方法,现实出现EXEC_BAD_ACCESS前访问的最后一个object。
有时程序崩溃根本不知错误发生在什么地方。 比如程序出现EXEC_BAD_ACCESS的时候,虽然大部分情况使用设定 NSZombieEnabled环境变量可以帮助你找到问题的所在,但少数情况下,即使设定了NSZombieEnabled环境变量,还是不知道程序崩 溃在什么地方。 那么就需要使用下列代码进行帮助了:
#ifdef _FOR_DEBUG_
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
#endif
你需要在每个object的.m或者.mm文件中加入上面代码,并且在 other c flags中加入-D _FOR_DEBUG_(记住请只在Debug Configuration下加入此标记)。 这样当你程序崩溃时,Xcode的console上就会准确地记录了最后运行的object的方法。
2. 通过 Zombie
如果打开了ARC或垃圾回收模式,在程序中发消息给已经释放的对象,将会引起程序崩溃。这时定位崩溃原因将非常困难,因为出问题的对象已经重新分配了。【MRC下对release的对象再访问;不支持ARC对象(CGImageRef)release之后再访问】
解决方法:可以通过启动僵尸对象(Zombie Objects)来解决,开启该选项后,程序在运行时,如果访问了已经释放的对象,则会给出较准确的定位信息,可以帮助确定问题所在。
功能的原理:在对象释放(retainCount 为0)时,使用一个内置的Zombie对象,替代原对象。
3. 设置全局断点快速定位问题代码所在行:
4. Xcode 7 已经集成了BAD_ACCESS捕获功能:Address Sanitizer。 用法如下:在配置中勾选?Enable Address Sanitizer
AddressSanitizer的原理:当程序创建变量分配一段内存时,将此内存后面的一段内存也冻结住,标识为中毒内存。