任何可能的原因是变量被重置为零?

时间:2011-10-20 16:28:07

标签: objective-c memory-management nsobject isa

我的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变量被重置了。它不一定是零。这次我发现它被重置为不同的值。而奇怪的是,它仍指向原始区域。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

您正在调用一个返回自动释放对象的类方法;尝试在实例化期间添加嵌套的保留,或者只使用alloc& init。

是的,指针指向原始地址,这就是它抛出异常的原因。如果指针设置为nil,则会因if语句而再次实例化对象。

答案 1 :(得分:2)

可能该对象已被释放,其内存在某些时候被重用。尝试使用Zombies乐器并查看。现在您已经发布了代码,我发现情况确实如此。 predicateWithFormat:方法返回一个你不拥有的实例,该实例在当前自动释放池的生命周期结束后可能会被释放。如果要保留它,则需要保留它(如果重新分配变量,则释放对象)。

答案 2 :(得分:0)

谢谢你们!这正是原因;保留我的对象后问题解决了。我认为我混淆了静态变量和它指向的底层数据。

BTW,对于可能对此问题感兴趣的其他人,您也可以参考此问题,Why retain a static variable?

这里学到的另一个教训是,无论何时isa变量被重置,都意味着对象进程被回收的内存。