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

根据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方法使用用户输入的字符串更新新创建的学生对象,然后通过[class addStudentObject:student]将该学生对象添加到其父类对象中。然后,用AddStudent.m弹出detailViewController([delegate addStudent:self didFinishWithSave:YES])。返回ClassRoster.m后,将保存managedObjectContext

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

更新:

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


选择一个现有的类对象(按其AddClass detailViewController)
选择查看班级名册
单击后退按钮以返回类对象detailView
选择以再次查看班级名册
选择添加新学生或选择现有学生对象
选择保存


在以下堆栈跟踪中,换行符用“ 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

最佳答案

这是更有可能的:


instanceVariable = [NSArray arrayWithObjects:..., nil];做某事
未保留NSArray,因此在运行循环结束时将其释放。
有东西敲打那排。 NSArray的内存被重用以创建您的ClassRoster对象。
您从ClassRoster中导航出来,它将被释放和取消分配。
某些东西试图访问instanceVariable。它指向曾经是NSArray的内存,但现在已被ClassRoster覆盖。


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

完成调试后将其关闭。

编辑:糟糕(我应该意识到您身上有僵尸,并查看了方法名称)。

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

关于iphone - -[ClassRoster controllerWillChangeContent:]:消息发送到已释放实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3479369/

10-10 03:58