使用NSZombie解决EXC_BAD_ACCESS问题

一.EXC_BAD_ACCESS问题

当向一个已经释放的对象发送消息时,就会使程序崩溃,但调试器仅打印出EXC_BAD_ACCESS错误,而没有其它信息提示是哪个对象导致的。
为了找到那那个提前被释放的对象,可以启动NSZombie。启用NSZombie后,对象被完全释放后就转化为NSZombie,但其内存并没有被释放,仍然可用。这时候向NSZombie(即已被完全释放的对象)发送消息时,因内存仍可用,程序不会crash,而调试器此时也可得知此已释放对象的地址,类型以及发向其的消息是什么。

二.解决方法

有两种方式启用NSZombie,一是设置NSZombieEnabled环境变量,二是使用Instruments的Zombies检测。

2.1 示例代码

iphone-memory-debug-nszombie中的ZombieDebug Demo Project代码来演示这两种方法,异常位置自己去找。

@implementation ZombieDebugViewController

@synthesize objArray;

-(void)rewriteText {
    NSMutableString* s = [NSMutableString stringWithCapacity:100];
    for (id obj in objArray) {
       [s appendFormat:@"%@,\n",obj];
       [obj release];
    }
    label.text = s;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.objArray = [NSMutableArray arrayWithCapacity:10];
    [objArray addObject:@"I'm a string object"];
    [self rewriteText];
}

-(IBAction) tapButton:(id)button {
    NSNumber* n = [NSNumber numberWithLong:random()];
    [objArray addObject:n];
    [self rewriteText];
}

-(void)dealloc {
    [super dealloc];
    self.objArray=nil;
}

@end
2.2.方法1-启用NSZombieEnabled环境变量

在xCode4中的设置方法为 Product->EditScheme->Run->Environment Variables, 添加NSZombieEnabled环境变量并设为YES。如图所示。

当设置NSZombieEnabled为YES后,运行程序,此时程序不再crash,而是在向已释放对象发送消息的位置断住,并在调试器中打印中引起异常对象的消息。如图所示

2012-05-29 22:47:10.911 ZombieDebug[828:f803] *** -[CFNumber respondsToSelector:]: message sent to deallocated instance 0x687c4e0


即向CFNumber对象发送respondsToSelector消息时检测到异常,0x687c4e0地址的CFNumber对象已经被释放。
注:因启动NSZombie后,本应释放的内存变成了NSZombie而不被释放,会使程序占用的内存越来越多,所以只能在调试时设置NSZombieEnabled环境变量,在发布时要去除。

使用NSZombieEnabled环境变量的方法只能知道哪个对象出了问题,而不知道该对象的分配释放流程,所以很难分析在哪一步出了问题,使用Instruments的NSZombie检测可以完整的跟踪对象的retain,release流程,从而分析哪一次释放为异常释放。

2.3 方法2-使用Instruments的NSZombie检测

使用菜单Product->Profile可以启动Instruments,如图所示,选择Zombies模板。

Zombies模板是Allocations模板的一个特例,其启用了Record Reference Counts和Enable NSZombie detection。

当Instruments中点击record运行程序,当有向NSZombie发送消息时,会有消息提醒。如图

点击图中的箭头后,就显示出此对象所有的retain,release,autorelease过程,便于分析哪里进行了不正常的释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值