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

Posted

技术标签:

【中文标题】过度释放导致的奇怪的核心数据错误?【英文标题】:Odd Core Data error caused by over releasing? 【发布时间】:2010-09-12 09:38:56 【问题描述】:

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

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

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];

视图控制器接口:

@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

所以在代码示例 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.

经过多次调试和拔毛后,我发现如果我不在 AddAccountViewControllerdealloc 方法中释放帐户,则应用程序会持续正常运行并且似乎不会根据仪器泄漏。

任何人都可以阐明发生了什么吗?我从有关属性的文档中了解到,需要释放那些保留的属性。我错过了什么?

更新以回答 Kevin 的问题

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();
        
      

【问题讨论】:

你能显示从 NSManagedObjectContext 中删除它的代码吗?这会发生在 AddAccountViewController 内部还是其他地方? childController.anAccount = account; 此行不保留account。它将它复制到anAccount。这根本不会 +1 它的保留,您只需在 AddAccountViewcontroller 的 dealloc 方法中释放 anAccount @Thomas: @property (nonatomic, retain) Account * anAccount; 为什么不保留? 托马斯,它不保留吗?它是声明为 retain 而不是 copy 的属性的合成集。 账户对象创建后是否保存对象上下文? 【参考方案1】:

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

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

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

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

【讨论】:

确实删除了第一个块末尾的[account release];意味着AddAccountViewController中的retainrelease得到了适当的平衡,并且在删除条目后保存时应用程序不会崩溃来自ManagedObjectContext。关于第一部分,我在模拟器和设备上运行代码并收到该错误。 SDK 为 4.1GM。 如果按照描述删除[account release]; 可以修复它,则 AddAccountViewController 被破坏(关于 Obj-C 内存管理约定)。如果不查看 AddAccountViewController 中涉及 anAccount 属性或其支持实例变量的所有代码,就很难确定它在哪里损坏。 (此外,在我所知道的任何编码约定中,都没有使用“a”或“an”作为属性/变量的前缀,并且与 Apple 使用它的地方相矛盾。)【参考方案2】:

我有一个类似的问题,以 a 结尾 “检测到尝试调用 iPhone 上不存在的系统库中的符号: _Unwind_Resume 从图像 CoreData 中的函数 _PFFaultHandlerLookupRow 调用。” 错误信息。

我的问题是模型中关系的错误“级联”删除规则。使用此规则,我的***托管对象被删除但仍在代码中引用。 将此关系的“删除规则”设置为“取消”后,一切都按设计进行。

--> 没有核心数据问题...设计问题!

强尼

【讨论】:

【参考方案3】:

当您删除任何托管对象时,系统将自动释放与该对象相关的所有引用。所以没有必要以编程方式实现对象。删除对象后,您将无法在父类中访问该对象。

【讨论】:

这不是真的。当一个托管对象被删除时,它被标记为删除,但它不能释放内存,因为它违反了苹果的内存管理策略。 我研究了那个NSManagedObjectContext类,我发现当deleteObject方法被调用时,对象会从唯一的表中删除。

以上是关于过度释放导致的奇怪的核心数据错误?的主要内容,如果未能解决你的问题,请参考以下文章

释放已使用数据的内存会导致分段错误

奇怪的核心数据错误

具有指定大小的自动释放 UIImages 的奇怪 malloc 错误

释放时填充结构数据会导致段错误

PHP 退出并出现“双重释放或损坏”错误

核心数据:重新打开文档时出现奇怪的绑定错误。帮助?