【问题标题】:Any possible reason isa variable is reset to nil?任何可能的原因 isa 变量被重置为零?
【发布时间】:2011-12-11 22:51:55
【问题描述】:

我的 iPhone 应用程序在运行一段时间后不断收到 BAD_EXC_ACCESS 错误,经过痛苦的调试后,我发现我的一个静态变量(确切地说是 NSPredicate)已损坏:它仍然指向原始地址,但它的 isa 变量已重置为 0!

这完全打败了我,为什么 isa 变量被重置为 0 ?!有什么想法吗?

谢谢!

更新:发布代码。代码其实来自erica's ABContactHelper我稍微改了一下,使用Predicate Templates让查询更高效,所以我加了这个功能:

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

有什么想法吗?

【问题讨论】:

  • BAD_EXC_ACCESS - 通常意味着您尝试使用已发布的对象。在此处发布您的“坏”代码

标签: objective-c memory-management nsobject


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 它是一个静态变量。它仍然指向原始地址,只是它的ias被重置了。我用完了解决方案:(
    • @Qiulang:你说的和被释放的对象没有任何关系。静态变量通常不会导致它们指向的东西变得不朽,并且被释放的对象不会导致指向该地址的指针重新分配给新地址。
    • @Qiulang 你应该试过了;您发布的代码存在僵尸会发现的内存问题。 (两个答案+1)
    • @NJones:不用担心。我想我们俩几乎是在同一时间发帖的,反正和别人说同样的话也没什么错。
    • OP,您对此答案的第一条评论表明您的困惑。静态变量仅表示类变量。所以是的,这个类是有一个名为 temp.. 的变量。你留下了指向地址 temp 的指针......即使在你存储在那里的自动释放对象被释放之后,因为你没有保留它。这就是为什么当你查看对象的 ISA 在哪里时,你会得到你认为是垃圾的东西,但实际上是现在存在的东西。
    【解决方案3】:

    谢谢大佬!这正是原因;在我保留我的对象后,问题就解决了。我想我对静态变量及其指向的基础数据感到困惑。

    顺便说一句,其他可能对此问题感兴趣的人,也可以参考这个,Why retain a static variable?

    这里学到的另一个教训是,每当 isa 变量被重置时,就意味着对象进程的内存已被回收。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-29
      • 2015-03-06
      • 2016-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-22
      相关资源
      最近更新 更多