- [ClassRoster controllerWillChangeContent:]:发送给解除分配实例的消息

时间:2010-08-13 17:40:32

标签: iphone core-data memory-management

我知道这些错误非常适合应用,并且几乎总是由于过度释放对象。我只是无法发现它,我读过的调试技巧还没有为我做过。

根据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中的对象被选中时,该对象被推送。

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

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

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

UPDATE:

我已经磨练了导致崩溃的一系列动作。如果我执行以下操作,我将始终在我的问题主题行中出现错误:

  1. 选择现有的类对象(推送其AddClass detailViewController)
  2. 选择查看班级“名册”
  3. 点击后退按钮返回到类对象detailView
  4. 选择再次查看班级名单
  5. 选择添加新学生或选择现有学生对象
  6. 选择保存
  7. 断裂线标有“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
    

4 个答案:

答案 0 :(得分:2)

以下是更有可能的事情:

  • 有事instanceVariable = [NSArray arrayWithObjects:..., nil];
  • NSArray未被保留,因此在运行循环结束时释放。
  • 有东西轻拍这一排。 NSArray的内存被重用来制作你的ClassRoster对象。
  • 您离开ClassRoster,它会被释放并解除分配。
  • 有些东西试图访问instanceVariable。它指向曾经是NSArray的内存,但现在已被ClassRoster覆盖。

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

完成调试后将其关闭。

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

如果在调试器中运行它(可能需要断点处于活动状态),应该停在调用controllerWillChangeContent:的东西上。也许你的ClassRoster被设置为某个东西的委托,并且在它被解除分配后得到一个委托回调?我总是将dealloc中的相关代表设置为nil,以防止出现这样的问题。

答案 1 :(得分:0)

我认为你没有过度发布该实例。

对我而言,看起来释放的实例属于其他类但接收来自ClassRoaster的消息。

您可以在应用崩溃的那一刻发布错误消息和堆栈跟踪吗?

答案 2 :(得分:0)

  

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

该行描述了这个问题。您可能正在使用Apple示例中的代码来构建多个NSManagedObjectContext正确吗?也许代码建议创建第二个,以便您可以轻松地取消编辑或其他一些?

这是你的问题。您正在尝试连接两个不同NSManagedObjectContext实例中的两个对象。考虑每个NSManagedObjectContext是一个沙箱,你不能混合它们。

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

更新

我发现了错误。您无法使用NSManagedObject创建-init。这不是NSManagedObject的指定初始值设定项。您必须使用

创建它
-initWithEntity: insertIntoManagedObjectContext:

或使用类方法

+[NSEntityDescription insertNewObjectForEntityForName: inManagedObjectContext]

这是创建新NSManagedObject的唯一两种有效方式。]

更新

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

我的原始假设仍然存在,某处,某种程度上,您试图连接两个不属于同一NSManagedObject的{​​{1}}个实例。您有两个NSManagedObjectContext个实例,或者您创建的NSManagedObjectContext没有关联的NSManagedObject

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

答案 3 :(得分:0)

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

祝你好运!