iOS开发那些事-性能优化–查找和解决僵尸对象
内存泄漏是当一个对象或变量在使用完成后没有释放掉,那么如果我们走了另外一个极端情况会什么样呢?这就导致过渡释放(over release)问题,从而使对象“僵尸化”,对象称为僵尸(zombies)对象。一个对象已经被释放过了,或者调用者没有这个对象的所有权而释放它, 都会造成过渡释放,产生僵尸对象。
僵尸对象或许对很多人听起来很恐怖、也很陌生,如果要说起EXEC_BAD_ACCESS异常,可能大家并不陌生。试图调用僵尸对象方法应用会崩溃(应用直接跳出),并抛出异常EXEC_BAD_ACCESS。
我们看看代码ViewController的代码片段:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listTeams objectAtIndex:row]; NSString *rowValue = [rowDict objectForKey:@"name"]; NSString *message = [[NSString alloc] initWithFormat:@”您选择了%@队。”, rowValue]; UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@”请选择球队” message:message delegate:self cancelButtonTitle:@”Ok” otherButtonTitles:nil]; [alert release]; ① [message release]; [alert show]; ② [tableView deselectRowAtIndexPath:indexPath animated:YES]; }
注意看程序代码的黑体部分,你会发现什么问题吗?程序运行的结果抛出EXEC_BAD_ACCESS异常。假设我们现在无法找到问题,可以使用 Instruments工具的Zombies跟踪模板。其中Instruments选择Zombies模板,点击Profile按钮就可以进入了。
点击Allocations的“i”按钮,弹出Target菜单配置Zombies模板,在Launch Configuration中勾选Record reference counts和Enable NSZombie detection。其中Record reference counts是显示引用计数,Enable NSZombie detection是能够检测僵尸对象。
这样在程序运行的时候,如果发现僵尸对象它就会弹出一个对话框,点击其中“→”按钮,在屏幕的下方会显示僵尸对象的详细信息。
僵尸对象为UIAlertView类型,从上到下僵尸对象是引用计数的变化是:创建 → 释放 → 僵尸化。打开扩展详细视图,在右边的跟踪堆栈信息进入我们程序代码,会打开对应代码,定位僵尸对象。
在上面的3条高亮显示的代码会影响对象引用计数,从中我们不难发现问题。关于解决方案就本例而言需要将代码②行的显示警告框的[alert show]语句,放在[alert release]语句之前调用就可以了。这就是僵尸对象问题。