iOS学习专题

iOS如何调试BAD_ACCESS错误、定位崩溃位置

2017-08-15  本文已影响88人  世玉茹花

写项目过程中经常遇到一些空指针或者僵尸对象问题,类似访问了野指针,比如对一个已经释放的对象执行了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的原理:当程序创建变量分配一段内存时,将此内存后面的一段内存也冻结住,标识为中毒内存。

AddressSanitizer比Zombie拥有更强大的捕获能力,特别是在malloc对象和内存越界方面。【在Build Settings中的Custom Compiler Flags下为other C Flags添加-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error】

上一篇下一篇

猜你喜欢

热点阅读