2017-07-26 84 views
1

我看到我有相同的核心数据堆栈跟踪应用程序的几个崩溃报告:的NSManagedObjectContext -save:引起SIGSEGV崩溃

enter image description here

我已经无法重现此崩溃,但我我认为它与级联删除NSManagedObject关系有关。这是通过调用堆栈跟踪中看到的_propagatePendingDeletesAtEndOfEvent:来判断的。我NSManagedObjectContext设置如下:

- (NSManagedObjectContext*)managedObjectContext { 
    if (_managedObjectContext == nil) { 
     _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
     [_managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 
    } 
    return _managedObjectContext; 
} 

上可能会造成什么来-save:来电与我的整个应用该堆栈跟踪崩溃任何想法?

+0

看起来像数据竞赛.. – Michael

回答

1

从堆栈跟踪我只能看出这是一个竞争条件,更具体在strong属性或可变数据的比赛,很可能在一本字典。由于崩溃发生在主线程上,我的第一个猜测是你在背景线程上使用了API,而后台线程不应该访问它。

  • 为什么我认为这是一场数据竞赛?
  • 由于竞争条件,核心数据代码在主线程上崩溃的最可能原因是什么?
  • 修复此错误的一些建议。

为什么我认为这是一个数据的比赛?

由于坠毁objc_retain发生。这只是经验。在我看到保留一个对象发生崩溃的10个案例中,有9个是因为数据竞赛。在另外一种情况下,罪魁祸首是手动进行内存管理错误。如果您对更多细节感兴趣,可以查看objc_storeStrong()的来源。

其次,Concurrency section in the Core Data Reference有这个有趣的信息:

NSMainQueueConcurrencyType是专门为您的应用程序接口的使用,并且只能在应用程序的主队列中。

的NSPrivateQueueConcurrencyType配置在初始化时创建自己的队列,并可以在该队列中仅使用。由于队列是NSManagedObjectContext实例的私有和内部队列,因此只能通过performBlock:和performBlockAndWait:方法访问该队列。

由于竞争条件,核心数据代码在主线程上崩溃的最可能原因是什么?

根据您问题中的代码,您正在使用NSMainQueueConcurrencyType,因此核心数据不应该在具有此“托管上下文”的背景队列上使用。

我的猜测是你正在从某个背景线程调用核心数据API。

固定这个错误有几个建议。

竞争情况并不总是导致崩溃。出于这个原因,这种崩溃有时不容易被重现。然而,所有的东西都不会丢失。

要查看它是否确实是数据竞赛,您必须查看完整的崩溃报告。通过崩溃报告,您不仅可以追踪崩溃的主线程,还可以在崩溃发生时追踪进程的所有其他线程。 (只需在崩溃报告中搜索“CoreData”)。如果您非常不走运,在任何后台线程上都不会显示核心数据API。在这种情况下,你至少应该看到一个有一些“autorelasepoolpop”框架的线程。如果您在后台堆栈跟踪中发现了一些“CoreData”帧,请在该堆栈跟踪中找到指向您的应用代码的帧。你有罪魁祸首。

为了进行调试,您可以在任何地方调用几个assert([NSThread isMainThread]);调用,无论您调用核心数据API。如果因断言失败而崩溃,则知道问题出在哪里。

如果您使用的是Xcode 9,您可能需要尝试新的“主线程清理程序”(在“诊断程序”下的方案设置中,在同一个面板中还配置了“线程清理程序”。想“暂停问题”)。如果这不起作用,请尝试使用“线程清洁剂”。

您也可以将并发类型切换为NSPrivateQueueConcurrencyType。请确保将所有核心数据API调用与performBlock:performBlockAndWait:调用包装在一起,否则您将不会获得更少的崩溃,但会导致更多的崩溃。如果您确实需要使用来自后台队列的核心数据,则可以采用这种方式。出于性能原因。

如果幸运的话,这只是一个小小的代码错误,可以在10分钟内修复:-)。如果你非常不走运,应用程序的并发架构就会崩溃,你必须(重新)设计它: - /。

希望这会有所帮助。

+0

感谢这是非常有益的。我会研究这些建议。 – hgwhittle

相关问题