【问题标题】:message sent to deallocated instance error发送到已释放实例错误的消息
【发布时间】:2015-02-10 23:14:08
【问题描述】:

我经常收到错误消息*** -[NSKeyValueObservance retain]: message sent to deallocated instance 0x86c75f10。我试过运行 Zombies 模板,这里是它提供的截图。

它指向一个 managedObject,我无法确定对象在哪里被释放。这是每次崩溃后编译器带我去的代码块。

- (void)setIsFavourite:(BOOL)isFavourite shouldPostToAnalytics:(BOOL)shouldPostToAnalytics;
{
    // check whether we need to generate preferences objects just in time
    if(!self.preferences && !self.series.preferences /*&& isFavourite*/)
    {
        if(self.series)
        {
            [self.series addPreferencesObject];
        }
        else
        {
            [self addPreferencesObject];
        }
    }

    //Crash In here
    self.preferences.isFavourite = @(isFavourite);
    self.series.preferences.isFavourite = @(isFavourite);

编辑:如果您需要查看更大尺寸的图像here 是更大分辨率的链接。

【问题讨论】:

  • 请发布更多您的托管对象实现。您是否正在覆盖访问器?您是否在访问原始值? CoreData 广泛使用 KVO。似乎对 CoreData 的某些内部方法的调用不平衡,这是非常不寻常的,并且似乎是问题的根源

标签: ios objective-c


【解决方案1】:

好的,我遇到了类似的问题,并找到了一种使用 NSKeyValueObservance 调试此类问题的方法。要调试,请执行以下操作:

  1. 在 Xcode 中,打开“Breakpoint Navigator”。
  2. 添加一个新的符号断点: -[NSKeyValueObservance _initWithObserver:property:options:context:originalObservable:]
  3. 在该断点处添加一个操作并将其设置为“调试器命令”。
  4. 设置以下命令:expr (void)NSLog(@"observer <0x%p>: %@ <%p>, property: %@", $arg1, (id)NSStringFromClass((id)[(id)$arg3 class]), $arg3, (id)$arg4)
  5. 点击“计算表达式后自动继续”。

现在您可以运行您的应用程序并采取必要的步骤来重现您的崩溃。是的,您需要启用 NSZombies。 注意:它会运行得很慢,而且你会得到大量的调试输出,但请耐心等待。它最终会到达那里。

当您尝试向已释放的 NSKeyValueObservance 发送消息时遇到崩溃时,您将看到原始对象的地址。突出显示地址并按 cmd-e 在搜索缓冲区中输入文本。然后点击 cmd-g 在调试器输出中查找字符串的下一个匹配项。您可能会多次找到该地址,因此请查找observer <0x?????> 输出后面的地址。该行的输出应该告诉您正在观察哪个对象以及哪个属性。

在我的情况下,当我弄清楚这一切时,结果发现我正在观察一个依赖于数组中对象的合成属性,并且在某个操作期间,数组中对象的顺序发生了变化而没有做正确的KVO 通知,这导致了我的崩溃。

【讨论】:

  • 在我的例子中,由于应用程序中的逻辑错误,在 deinit/dealloc 期间,KVO 观察者被添加回堆栈。稍后,KVO API 尝试向已释放的实例发送通知。不错。
【解决方案2】:

您是否使用手动引用计数?如果是这样,为什么?将您的应用程序转换为 ARC。手动引用计数充其量是痛苦的,而 ARC 则要好得多。

我是一位经验丰富的 iOS 和 Mac OS 开发人员,两者都可以,但我更喜欢 ARC。它不那么繁琐和容易出错。

Xcode 中内置了一项功能,可以为您将项目转换为 ARC。您可能需要做一些事后清理工作,但这是值得的。

如果你这样做,你的问题可能会消失。

至于细节,您的屏幕截图太小,无法阅读。如果您希望有人试图弄清楚发生了什么,您将需要发布一张全尺寸的图片。

但是,从广义上讲,我觉得您有一个自动释放错误。

在手动引用计数代码中,许多系统方法返回“自动释放”的对象。这意味着当您收到它们时,它们的保留计数是正数(通常为 1),因此它们会留下来。但是,它们已被添加到“自动释放池”中,这意味着如果没有人先保留它们,它们将在下一次通过事件循环时被释放。

当您收到一个自动释放的对象时,您应该接受一旦您当前的方法返回就会释放它,或者保留它。

如果您尝试使用手动引用计数来编写 Core Data 代码并且不理解这一点,那么您就是在为失败做好准备。

Core Data 相当复杂,在尝试编写使用它的程序之前,您应该对 Cocoa 内存管理有深入的了解,尤其是如果您使用手动引用计数。

【讨论】:

  • 我正在使用 ARC,但是我确实有需要手动设置的核心基础对象。
  • 也上传了大图。
  • 有问题的对象是 NSManagedObject?这些是 NSObject,由 ARC 管理。你在处理什么 CF 对象?
  • 我怀疑正在发生的事情是 MOC 正在被释放,而部分代码正在尝试修改托管对象。我想知道如何确保 MOC 在其对象仍然存在时仍然存在。尤其是当这些物体被四处传递时。
  • 您是否尝试从多个线程访问核心数据?它不是多线程的。如果我没记错的话,你必须从同一个线程对 MOC 进行所有访问。
猜你喜欢
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多