我的iPhone应用程序在运行一段时间后仍然收到BAD_EXC_ACCESS错误,经过痛苦的调试后我发现我的一个静态变量(确切地说是NSPredicate)已损坏:它仍指向原始地址,但其isa变量已重置到0!
这完全打败了我,为什么isa变量被重置为0?有什么想法吗?
谢谢!
更新:发布代码。代码实际上来自erica's ABContactHelper我稍微改了一下使用谓词模板来提高查询效率,所以我添加了这个函数:
+ (NSPredicate*) predicateforMatchingName:(NSString*) name {
//templateForMatchingName is a static variable I declare elsewhere
//static NSPredicate * templateForMatchingName =nil;
if (templateForMatchingName == nil) {
templateForMatchingName = [NSPredicate predicateWithFormat:@"firstname contains[cd] $NAME1 OR lastname contains[cd] $NAME2 OR nickname contains[cd] $NAME3 OR middlename contains[cd] $NAME4"];
}
NSDictionary *sub = [NSDictionary dictionaryWithObjectsAndKeys:
name,@"NAME1",
name,@"NAME2",
name,@"NAME3",
name,@"NAME4",
nil];
NSPredicate *pred = [templateForMatchingName predicateWithSubstitutionVariables:sub];
return pred;
}
我认为这段代码是完美的“普通”,templateForMatchingName在创建后无法更改。但后来我发现它的isa变量被重置了。它不一定是零。这次我发现它被重置为不同的值。而奇怪的是,它仍指向原始区域。
有什么想法吗?
答案 0 :(得分:3)
您正在调用一个返回自动释放对象的类方法;尝试在实例化期间添加嵌套的保留,或者只使用alloc& init。
是的,指针指向原始地址,这就是它抛出异常的原因。如果指针设置为nil,则会因if语句而再次实例化对象。
答案 1 :(得分:2)
可能该对象已被释放,其内存在某些时候被重用。尝试使用Zombies乐器并查看。现在您已经发布了代码,我发现情况确实如此。 predicateWithFormat:方法返回一个你不拥有的实例,该实例在当前自动释放池的生命周期结束后可能会被释放。如果要保留它,则需要保留它(如果重新分配变量,则释放对象)。
答案 2 :(得分:0)
谢谢你们!这正是原因;保留我的对象后问题解决了。我认为我混淆了静态变量和它指向的底层数据。
BTW,对于可能对此问题感兴趣的其他人,您也可以参考此问题,Why retain a static variable?这里学到的另一个教训是,无论何时isa变量被重置,都意味着对象进程被回收的内存。