NSError 释放:消息发送到释放的实例

Posted

技术标签:

【中文标题】NSError 释放:消息发送到释放的实例【英文标题】:NSError release: message sent to deallocated instance 【发布时间】:2014-03-17 17:15:38 【问题描述】:

我的 ios 7 应用程序崩溃并出现以下错误:

-[NSError release]: message sent to deallocated instance 0x3c443fe0

当我添加对以下方法的调用时引发错误:

-(void)loadMessages:(NSString*)customerUID 
  NSString *formatUID = [NSString stringWithFormat:@"%s%@%s", "'", customerUID, "'"];
  formatUID = [formatUID stringByReplacingOccurrencesOfString:@"'" withString:@"%27"];
  NSString *servicePath = [NSString stringWithFormat:@"/api/messagerecipient?messageid=null&customeruid=%@", formatUID];

  [[RKObjectManager sharedManager] getObjectsAtPath:servicePath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *messagesResult)
  
    NSArray *messageResults = messagesResult.array;

    if (messageResults != nil || [messageResults count] != 0)
    
      //Add some code here
    
   failure:^(RKObjectRequestOperation *operation, NSError *error) 

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"An Error Has Occurred" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertView show];
  ];

我在代码的不同点添加了多个断点,但它没有返回任何错误详细信息。此外,控制台日志中没有任何内容表明问题出在哪里(我添加了完整的 RestKit 日志记录),只是上面的 NSError 发布消息。

我还在 Instruments 中运行了 Zombie 扫描。它显示以下内容。

我很困惑,因为这表明僵尸是由GSEventRunModal 调用创建的。当我转到扩展详细信息并选择呼叫时,它显示以下内容:

任何指点将不胜感激,谢谢。

更新:仪器扩展详细信息堆栈跟踪

【问题讨论】:

那么是什么让您认为这与 RestKit 相关?如果您不拨打 RestKit 电话,那么您就没有问题吗? 是的,没错,但不确定它是否与 RestKit 有关。命中的最后一个断点在 AFURLConnectionOperation, operationDidStart 方法中。似乎抛出错误的进程是_CFRunLoopRun。 您的映射应该创建托管对象并插入到存储中?提出此请求时,您有哪些未保存的内容?您还同时使用 Core Data 做什么? 对于分配了NSError 的站点,从扩展的详细信息窗格中查看整个堆栈跟踪会很有用。 僵尸不是由GSEventRunModal 创建的。当您在 GSEventRunModal 中看到 Release 时,表示自动释放池正在耗尽。事件历史记录中的最后一行(第 7 行)是一个额外的释放(被发送到在第 6 行变成僵尸的 NSError),因为 NSError 被自动释放太多次。 【参考方案1】:

我也经常看到这种情况,问题的根源似乎在于 Core Data。我使用 MagicalRecord 数据库库(RestKit 也是如此),我们认为错误就在那里。你可以看到一个讨论here。经过我们所有的调查,MagicalRecord 似乎是正确的,而 Core Data 是错误的。

这实际上已作为 Apple 声称已修复的错误提交,但我们仍然看到它。我能够解决此问题的唯一方法是阻止我可能无法保存数据的每个实例,因此不会报告错误。您可以在上面链接的讨论帖中看到其中的一些提示。

【讨论】:

虽然它没有解决我的问题 - 你的回答很好地解释了问题所在 - 因此奖励你赏金......为你的帮助干杯!【参考方案2】:

可能是您试图从块内显示 AlertView 吗?与 UI 的交互必须在主线程上?

How do display a UIAlertView from a block on iOS?

【讨论】:

【参考方案3】:

你可以尝试替换吗:

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"An Error Has Occurred" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertView show];

与:

NSString * message = [error localizedDescription];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"An Error Has Occurred" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertView show];

虽然我猜init方法无论如何都会得到一个字符串。

【讨论】:

【参考方案4】:

我认为你的问题不在于它自己的方法。

错误消息表明您正在向 NSERROR 类型的对象发送释放调用。

请检查包含您正在调用的方法的类的实例,并确保它没有被释放。

或将调用方法添加到问题中以便我们检查。

【讨论】:

【参考方案5】:

在我的情况下,将数据库线程化到单独的上下文会有所帮助。我在接收消息的类上使用了以下构造函数:

    -(id)init 
    self = [super init];
    if (self) 
        self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        self.managedObjectContext.parentContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
        self.managedObjectContext.retainsRegisteredObjects = YES;
    

    return self;

【讨论】:

以上是关于NSError 释放:消息发送到释放的实例的主要内容,如果未能解决你的问题,请参考以下文章

发送到已释放实例的消息

发送到已释放实例问题的消息

[CustomViewController respondsToSelector:]:消息发送到释放的实例

[UIImageAsset 保留]:发送到已释放实例的消息

-[CALayer release]:消息发送到释放的实例

[UINavigationController 保留]:发送到已释放实例的消息