过度释放导致奇数核心数据错误?

tar*_*sis 6 iphone cocoa-touch core-data objective-c ios

偶尔的读者和第一次问题提问者,所以请温柔:)

我正在创建一个托管对象(帐户),它被传递到子视图控制器,在该视图控制器中,它被保留在一个属性中.

Account * account = [[Account alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
AddAccountViewController *childController = [[AddAccountViewController alloc] init];
childController.title = @"Account Details"; 
childController.anAccount = account;
childController.delegate = self;

[self.navigationController pushViewController:childController animated:YES];
[childController release];
[account release];
Run Code Online (Sandbox Code Playgroud)

视图控制器界面:

@interface AddAccountViewController : UIViewController {
}

@property (nonatomic, retain) IBOutlet UITextField * usernameTextField;
@property (nonatomic, retain) IBOutlet UITextField * passwordTextField;

@property (nonatomic, retain) Account * anAccount;
@property (nonatomic, assign) id <AddAccountDelegate> delegate;

- (IBAction)cancel:(id)sender;
- (IBAction)add:(id)sender;
- (IBAction)textFieldDone:(id)sender;
@end
Run Code Online (Sandbox Code Playgroud)

所以在代码示例1中,我发布了帐户对象,因为我不再对该方法感兴趣.由于AddAccountViewController保留了它,我在AddAccountViewControllerdealloc中有一个条目释放它.

但是,当我从ManagedObjectContext删除对象时,应用程序崩溃时出现以下(相当不清楚)错误:

Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
_Unwind_Resume called from function _PFFaultHandlerLookupRow in image CoreData.
Run Code Online (Sandbox Code Playgroud)

经过大量的调试和拔毛后,我发现如果我不在AddAccountViewControllerdealloc方法中释放帐户,那么应用程序可以连续正常工作,并且根据Instruments不会泄漏.

任何人都可以说明最新情况吗?我从有关属性的文档中了解到需要释放的属性.我错过了什么?

更新回答凯文的问题

ManagedObjectContext中删除对象的代码位于RootViewController中(持有子控制器)

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the managed object for the given index path
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];

        [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

        // Save the context.
        NSError *error = nil;
        if (![context save:&error]) {
            /*
             Replace this implementation with code to handle the error appropriately.

             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
             */
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }  
}
Run Code Online (Sandbox Code Playgroud)

tc.*_*tc. 1

首先:这听起来像是苹果公司的一个错误。Core Data 正在调用_Unwind_Resume,这(可能)是某种异常展开。手机上存在异常展开,但(我认为)使用 ARM ABI,它使用以__cxa_. 你是在模拟器上运行的吗?哪个版本的SDK?

当您删除对 的调用时,可能会有一个额外的版本漂浮在“平衡”的某个地方[account release];

“仪器未显示任何泄漏”并不意味着没有泄漏;最后我检查它被循环混淆了(即如果你忘记在 dealloc 中取消设置 IBOutlets,它不会显示泄漏)。我测试过NSMutableData * d = [NSMutableData dataWithLength:1<<20]; memcpy(d.mutableBytes, &d, 4);,但更简单的测试只是[[UIView alloc] initWithFrame:CGRectZero]

如果您认为这是保留/释放问题,我曾经通过覆盖保留/释放/自动释放来调用 NSLog 来调试这些问题。然后我在所有这些上添加了断点,将它们设置为运行命令“bt”,然后单击“自动继续”。然后运行中断的东西(在我的例子中,我认为这只是一个额外的保留),打印出日志输出,将其粘贴在白板上,并花半个小时匹配保留和释放。