gpt4 book ai didi

ios - NSManagedObjectContext -保存: causing SIGSEGV crash

转载 作者:行者123 更新时间:2023-12-01 16:02:26 25 4
gpt4 key购买 nike

我看到我的应用程序有几个具有相同核心数据堆栈跟踪的崩溃报告:

enter image description here

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

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

对于什么可能导致对 -save: 的调用因整个应用程序中的堆栈跟踪而崩溃,您有什么想法吗?

最佳答案

从堆栈跟踪中我只能看到它是一个竞争条件,更具体地说是强属性或变量(可能在字典中)的数据竞争。由于崩溃发生在主线程上,我的第一个猜测是您在后台线程上使用了不应在后台线程上访问的 API。

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

为什么我认为这是一场数据竞争?

因为崩溃发生在objc_retain中。这只是经验。在我看到因保留对象而崩溃的情况中,十分之九是因为数据争用。在另一种情况下,罪魁祸首是手动内存管理做得错误。如果您对更多细节感兴趣,可以查找 objc_storeStrong() 的源码。

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

NSMainQueueConcurrencyType is specifically for use with your application interface and can only be used on the main queue of an application.

The NSPrivateQueueConcurrencyType configuration creates its own queue upon initialization and can be used only on that queue. Because the queue is private and internal to the NSManagedObjectContext instance, it can only be accessed through the performBlock: and the performBlockAndWait: methods.

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

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

我的猜测是您正在从某个后台线程调用核心数据 API。

修复此错误的一些建议。

竞争条件并不总是会导致崩溃。因此,有时无法轻易重现此类崩溃。然而,一切并没有失去。

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

为了进行调试,您可以在各处调用一些 assert([NSThread isMainThread]); 调用,无论您在何处调用核心数据 API。如果由于断言失败而崩溃,您就知道问题出在哪里。

如果您使用的是 Xcode 9,您可能想尝试新的“Main Thread Sanitizer”(在“Diagnostics”下的方案设置中,在还配置了“Thread Sanitizer”的同一面板中。您可能想要“暂停讨论问题”)。如果这没有帮助,还可以尝试“Thread Sanitizer”。

您还可以将并发类型切换为 NSPrivateQueueConcurrencyType。请务必使用 performBlock:performBlockAndWait: 调用包装所有核心数据 API 调用,否则您不会得到更少的崩溃,而是更多的崩溃。如果您确实需要使用后台队列中的核心数据(例如出于性能原因。

如果你幸运的话,这只是某个地方的一个微小的代码错误,可以在 10 分钟内修复:-)。如果您非常不幸,应用程序的并发架构已损坏,您必须(重新)设计它:-/。

希望这有帮助。

关于ios - NSManagedObjectContext -保存: causing SIGSEGV crash,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45337339/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com