【问题标题】:-[ClassRoster controllerWillChangeContent:]: message sent to deallocated instance-[ClassRoster controllerWillChangeContent:]:消息发送到释放的实例
【发布时间】:2011-03-29 14:33:10
【问题描述】:

我知道这些错误是非常特定于应用程序的,并且几乎总是由于过度释放对象。我只是无法发现它,而且我阅读的调试技巧还没有为我解决问题。

根据this debugging advice,我的“违规对象”被分配在这个代码块中(位于AddClass.m):

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row == 1) {

        ClassRoster *classRoster = [[ClassRoster alloc] init];
        classRoster.managedObjectContext = managedObjectContext;
        classRoster.newClass = self.newClass;

        classRoster.title = @"Class Roster";
        [self.navigationController pushViewController:classRoster animated:YES];
        [classRoster release];

    }
}

但是,我不明白违规对象是如何从这里来的。我相信我正在适当地释放classRoster,并且没有分配任何其他内容。

错误消息清楚地表明程序试图更新我的classRoster TableViewController 中的对象。这是有道理的,因为当我尝试在ClassRoster的DetailViewController(AddStudent.m)中保存一个对象时,崩溃发生在被选中classRoster classRoster的对象时。

为了给出这个问题的更广泛的背景,我正在使用 Core Data 并且(从上面的代码中可以看到)在视图之间传递一个 managedObjectContext,以便编辑和保存类列表及其相关类名册。我正在使用[managedObjectContext rollback] 取消更改。

值得一提的是,AddStudent.m 中的 save 方法使用用户输入的字符串更新新创建的学生对象,然后通过[class addStudentObject:student]将该学生对象添加到其父类对象中。然后使用[delegate addStudent:self didFinishWithSave:YES] 弹出detailViewController (AddStudent.m)。返回ClassRoster.m 后,managedObjectContext 被保存。

如果您认为我的核心数据管理可能是问题所在,请告诉我您希望查看的代码。这是我的第一个应用程序,因此我很高兴犯了很多愚蠢的错误!

更新:

我已经仔细研究了导致崩溃的一系列操作。如果我执行以下操作,我总是会因问题主题行中的错误而崩溃:

  1. 选择一个现有的类对象(按下它的 AddClass detailViewController)
  2. 选择查看班级名单
  3. 点击返回按钮返回类对象detailView
  4. 选择再次查看班级名单
  5. 选择添加新学生或选择现有学生对象
  6. 选择保存

在以下堆栈跟踪中,断行由“BREAK >>”标记:

0x01e8c2f0  <+0000>  push   %ebp
0x01e8c2f1  <+0001>  mov    %esp,%ebp
0x01e8c2f3  <+0003>  push   %edi
0x01e8c2f4  <+0004>  push   %esi
0x01e8c2f5  <+0005>  push   %ebx
0x01e8c2f6  <+0006>  sub    $0x5c,%esp
0x01e8c2f9  <+0009>  call   0x1e8c2fe <___forwarding___+14>
0x01e8c2fe  <+0014>  pop    %ebx
0x01e8c2ff  <+0015>  mov    0xc(%ebp),%esi
0x01e8c302  <+0018>  test   %esi,%esi
0x01e8c304  <+0020>  je     0x1e8c620 <___forwarding___+816>
0x01e8c30a  <+0026>  mov    0x8(%ebp),%eax
0x01e8c30d  <+0029>  add    $0x4,%eax
0x01e8c310  <+0032>  mov    0x8(%ebp),%edx
0x01e8c313  <+0035>  mov    0x4(%edx),%edx
0x01e8c316  <+0038>  mov    %edx,-0x30(%ebp)
0x01e8c319  <+0041>  mov    0x4(%eax),%eax
0x01e8c31c  <+0044>  mov    %eax,-0x2c(%ebp)
0x01e8c31f  <+0047>  mov    -0x30(%ebp),%ecx
0x01e8c322  <+0050>  mov    %ecx,(%esp)
0x01e8c325  <+0053>  call   0x1f0a11e <dyld_stub_object_getClass>
0x01e8c32a  <+0058>  mov    %eax,(%esp)
0x01e8c32d  <+0061>  call   0x1f09e5a <dyld_stub_class_getName>
0x01e8c332  <+0066>  mov    %eax,-0x28(%ebp)
0x01e8c335  <+0069>  movl   $0xa,-0x34(%ebp)
0x01e8c33c  <+0076>  cld    
0x01e8c33d  <+0077>  lea    0x73a30(%ebx),%edi
0x01e8c343  <+0083>  mov    %eax,%esi
0x01e8c345  <+0085>  mov    $0xa,%ecx
0x01e8c34a  <+0090>  repz cmpsb %es:(%edi),%ds:(%esi)
0x01e8c34c  <+0092>  mov    $0x0,%eax
0x01e8c351  <+0097>  je     0x1e8c35d <___forwarding___+109>
0x01e8c353  <+0099>  movzbl -0x1(%esi),%eax
0x01e8c357  <+0103>  movzbl -0x1(%edi),%ecx
0x01e8c35b  <+0107>  sub    %ecx,%eax
0x01e8c35d  <+0109>  test   %eax,%eax
0x01e8c35f  <+0111>  jne    0x1e8c3a7 <___forwarding___+183>
0x01e8c361  <+0113>  mov    0x95d46(%ebx),%eax
0x01e8c367  <+0119>  cmpb   $0x0,(%eax)
0x01e8c36a  <+0122>  jne    0x1e8c680 <___forwarding___+912>
0x01e8c370  <+0128>  mov    -0x2c(%ebp),%edx
0x01e8c373  <+0131>  mov    %edx,(%esp)
0x01e8c376  <+0134>  call   0x1f0a214 <dyld_stub_sel_getName>
0x01e8c37b  <+0139>  mov    -0x30(%ebp),%ecx
0x01e8c37e  <+0142>  mov    %ecx,0x10(%esp)
0x01e8c382  <+0146>  mov    %eax,0xc(%esp)
0x01e8c386  <+0150>  mov    -0x28(%ebp),%eax
0x01e8c389  <+0153>  add    $0xa,%eax
0x01e8c38c  <+0156>  mov    %eax,0x8(%esp)
0x01e8c390  <+0160>  lea    0x9d822(%ebx),%eax
0x01e8c396  <+0166>  mov    %eax,0x4(%esp)
0x01e8c39a  <+0170>  movl   $0x3,(%esp)
0x01e8c3a1  <+0177>  call   0x1eb3040 <CFLog>
0x01e8c3a6  <+0182>  int3   
BREAK >> 0x01e8c3a7  <+0183>  movl   $0x11,-0x38(%ebp)
0x01e8c3ae  <+0190>  cld    
0x01e8c3af  <+0191>  lea    0x79590(%ebx),%edi
0x01e8c3b5  <+0197>  mov    -0x28(%ebp),%esi
0x01e8c3b8  <+0200>  mov    $0x11,%ecx
0x01e8c3bd  <+0205>  repz cmpsb %es:(%edi),%ds:(%esi)
0x01e8c3bf  <+0207>  mov    $0x0,%eax
0x01e8c3c4  <+0212>  je     0x1e8c3d0 <___forwarding___+224>
0x01e8c3c6  <+0214>  movzbl -0x1(%esi),%eax
0x01e8c3ca  <+0218>  movzbl -0x1(%edi),%ecx
0x01e8c3ce  <+0222>  sub    %ecx,%eax
0x01e8c3d0  <+0224>  mov    -0x30(%ebp),%edx
0x01e8c3d3  <+0227>  mov    %edx,-0x24(%ebp)
0x01e8c3d6  <+0230>  test   %eax,%eax
0x01e8c3d8  <+0232>  jne    0x1e8c3e0 <___forwarding___+240>
0x01e8c3da  <+0234>  mov    0x4(%edx),%ecx
0x01e8c3dd  <+0237>  mov    %ecx,-0x24(%ebp)
0x01e8c3e0  <+0240>  mov    0xa1dbe(%ebx),%esi
0x01e8c3e6  <+0246>  mov    -0x24(%ebp),%eax
0x01e8c3e9  <+0249>  mov    %eax,(%esp)
0x01e8c3ec  <+0252>  call   0x1f0a11e <dyld_stub_object_getClass>
0x01e8c3f1  <+0257>  mov    %esi,0x4(%esp)
0x01e8c3f5  <+0261>  mov    %eax,(%esp)
0x01e8c3f8  <+0264>  call   0x1f09e72 <dyld_stub_class_respondsToSelector>
0x01e8c3fd  <+0269>  test   %al,%al
0x01e8c3ff  <+0271>  je     0x1e8c580 <___forwarding___+656>
0x01e8c405  <+0277>  mov    -0x2c(%ebp),%edx
0x01e8c408  <+0280>  mov    %edx,0x8(%esp)
0x01e8c40c  <+0284>  mov    %esi,0x4(%esp)
0x01e8c410  <+0288>  mov    -0x24(%ebp),%ecx
0x01e8c413  <+0291>  mov    %ecx,(%esp)
0x01e8c416  <+0294>  call   0x1f0a0ee <dyld_stub_objc_msgSend>
0x01e8c41b  <+0299>  mov    %eax,-0x20(%ebp)
0x01e8c41e  <+0302>  mov    %eax,-0x1c(%ebp)
0x01e8c421  <+0305>  test   %eax,%eax
0x01e8c423  <+0307>  je     0x1e8c5ac <___forwarding___+700>
0x01e8c429  <+0313>  mov    0xa1df6(%ebx),%eax
0x01e8c42f  <+0319>  mov    %eax,0x4(%esp)
0x01e8c433  <+0323>  mov    -0x1c(%ebp),%edx
0x01e8c436  <+0326>  mov    %edx,(%esp)
0x01e8c439  <+0329>  call   0x1f0a0ee <dyld_stub_objc_msgSend>
0x01e8c43e  <+0334>  mov    (%eax),%edx
0x01e8c440  <+0336>  mov    0x18(%edx),%eax
0x01e8c443  <+0339>  shr    $0x16,%eax
0x01e8c446  <+0342>  and    $0x1,%eax
0x01e8c449  <+0345>  cmp    0xc(%ebp),%eax
0x01e8c44c  <+0348>  je     0x1e8c498 <___forwarding___+424>
0x01e8c44e  <+0350>  lea    0x6eaee(%ebx),%eax
0x01e8c454  <+0356>  lea    0x7979f(%ebx),%esi
0x01e8c45a  <+0362>  mov    0xc(%ebp),%ecx
0x01e8c45d  <+0365>  test   %ecx,%ecx
0x01e8c45f  <+0367>  mov    %eax,%edi
0x01e8c461  <+0369>  cmove  %esi,%edi
0x01e8c464  <+0372>  testb  $0x40,0x1a(%edx)
0x01e8c468  <+0376>  cmovne %eax,%esi
0x01e8c46b  <+0379>  mov    -0x2c(%ebp),%ecx
0x01e8c46e  <+0382>  mov    %ecx,(%esp)
0x01e8c471  <+0385>  call   0x1f0a214 <dyld_stub_sel_getName>
0x01e8c476  <+0390>  mov    %edi,0x10(%esp)
0x01e8c47a  <+0394>  mov    %esi,0xc(%esp)
0x01e8c47e  <+0398>  mov    %eax,0x8(%esp)
0x01e8c482  <+0402>  lea    0x9d852(%ebx),%eax
0x01e8c488  <+0408>  mov    %eax,0x4(%esp)
0x01e8c48c  <+0412>  movl   $0x4,(%esp)
0x01e8c493  <+0419>  call   0x1eb3040 <CFLog>
0x01e8c498  <+0424>  mov    -0x20(%ebp),%eax
0x01e8c49b  <+0427>  mov    %eax,0x8(%esp)
0x01e8c49f  <+0431>  mov    0xa1dba(%ebx),%eax
0x01e8c4a5  <+0437>  mov    %eax,0x4(%esp)
0x01e8c4a9  <+0441>  mov    0xa1e76(%ebx),%eax
0x01e8c4af  <+0447>  mov    %eax,(%esp)
0x01e8c4b2  <+0450>  call   0x1f0a0ee <dyld_stub_objc_msgSend>
0x01e8c4b7  <+0455>  mov    %eax,%edi
0x01e8c4b9  <+0457>  mov    0xa1dde(%ebx),%eax

【问题讨论】:

    标签: iphone core-data memory-management


    【解决方案1】:

    以下是更有可能的情况:

    • 有些事情instanceVariable = [NSArray arrayWithObjects:..., nil];
    • NSArray 没有被保留,所以它在运行循环结束时被释放。
    • 有东西在敲击行。 NSArray 的内存被重用于创建 ClassRoster 对象。
    • 您从 ClassRoster 中导航出来,然后它会被释放和解除分配。
    • 有东西试图访问 instanceVariable。它指向曾经是 NSArray,但现在已被 ClassRoster 覆盖的内存。

    尝试设置环境变量 NSZombieEnabled=YES(在 Project -> Edit Active Executable 中)。您也可以设置 NSDeallocateZombies=NO,但 AIUI 是默认设置。

    完成调试后将其关闭。

    编辑:哎呀(我应该已经意识到你有僵尸,并查看了方法名称)。

    如果您在调试器中运行它(您可能需要激活断点),它应该停在名为 controllerWillChangeContent: 的地方。也许您的 ClassRoster 被设置为某事的委托,并且在它被释放后正在获得委托回调?我总是在 dealloc 中将相关代表设置为 nil 以防止出现此类问题。

    【讨论】:

    • 我已经有 NSZombieEnabled=YES。这是否应该在崩溃时自动在控制台中提供更多信息,还是我需要输入命令来检查僵尸对象?
    • 嗯...是的,它是 detailView 的委托,它被推送到它上面,以便它可以接收有关用户是否选择保存的通知。您会建议放弃这种方法,还是有一种“适合代码”的方法可以防止 ClassRoster 被释放?附言我更新了我的帖子。
    • 在 dealloc 中,detailView.delegate = nil (但不应该先解除详细视图吗?)。
    • 在我设置为其后续 detailViewControllers 的代表的两个视图控制器中,我将 detailView.delegate = nil 添加到 -dealloc。然后我在一个委托视图控制器上点击后退按钮后收到此错误:-[AddStudent setDelegate:]: message sent to deallocated instance 0x458ea20
    • 当然,你需要在[detailView release]之前做detailView.delegate = nil(我假设detailView是一个AddStudent*)。
    【解决方案2】:

    我认为你没有过度释放实例。

    在我看来,释放的实例似乎属于其他类,但收到了来自 ClassRoaster 的消息。

    您能否发布应用程序崩溃时的错误消息和堆栈跟踪?

    【讨论】:

    • 我的问题主题是控制台中显示的完整错误。我不熟悉使用堆栈跟踪。如果我打开 Run -> Debugger,那是大量的地址列表吗?
    【解决方案3】:

    '非法尝试在不同上下文中的对象之间建立关系'myClass''

    该行描述了该问题。您可能正在使用来自 Apple 示例的代码,该示例构建了多个 NSManagedObjectContext 对吗?也许代码建议创建第二个,以便您可以轻松取消编辑等?

    那是你的问题。您正在尝试连接位于两个不同 NSManagedObjectContext 实例中的两个对象。将每个NSManagedObjectContext 视为一个沙盒,您不能将它们混合使用。

    但是,您不需要拥有多个 NSManagedObjectContext。这样做的例子是一个非常糟糕的例子。对于任何单线程应用程序来说,单个NSManagedObjectContext 绰绰有余。从您的应用程序中删除第二个NSManagedObjectContext,这个问题就会消失。

    更新

    我发现了错误。您不能使用-init 创建NSManagedObject。这不是NSManagedObject 的指定初始化程序。您必须使用

    创建它
    -initWithEntity: insertIntoManagedObjectContext:
    

    或者使用类方法

    +[NSEntityDescription insertNewObjectForEntityForName: inManagedObjectContext]
    

    这是创建新 NSManagedObject 的仅有的两种有效方法。]

    更新

    强烈建议您使用更好的命名约定,ClassRosterViewController 更具描述性。 ClassRoster 听起来确实像数据对象。

    我最初的假设仍然存在,不知何故,您试图连接两个不属于同一个NSManagedObjectContextNSManagedObject 实例。要么您有两个 NSManagedObjectContext 实例,要么您正在创建一个没有关联 NSManagedObjectContextNSManagedObject

    但是,我的回答是基于您问题中的错误消息。您在哪里看到标题中的错误。您也可以粘贴那个堆栈跟踪吗?

    【讨论】:

    • 我只有一个 NSManagedObjectContext(参见我在第一个代码块之后的第三段),我首先将它传递给我的 RootViewController,然后再传递给每个后续控制器(尽管将整个上下文传递给每个上述观点可能是矫枉过正)。我仍在使用 Apple CoreDataBooks 示例中使用的委托通知(即-didFinishWithSave),但我只使用了一个 MOC。
    • 如果您指的是我的第一个代码块,那里没有初始化NSManagedObjectClassRoster 是一个 UITableViewController,我将其推入堆栈。但是,我在其他地方仔细检查了我的 NSManagedObject 初始化,它们都与您上面列出的两个初始化器匹配。
    • 堆栈跟踪现在列在更新中。我为我的命名约定道歉。我现在正在改变它们。
    【解决方案4】:

    刚刚遇到同样的问题 问题是因为我释放了委托而不是将其设置为 nil

    祝你好运!

    【讨论】:

      猜你喜欢
      • 2023-03-13
      • 2011-12-04
      • 2012-08-22
      • 1970-01-01
      • 2016-08-28
      • 2011-06-16
      • 2013-08-30
      相关资源
      最近更新 更多