2010-06-09 103 views
0

我有一个NSOperation,它从核心数据持久性存储中提取一些对象并总计几个总数。有时一个对象在正在进行的操作中被删除,因此发生核心数据错误异常。我尝试/捕捉异常,同时忽略它,因为我只是想跳过那些不会出错的对象。错误异常会导致在[NSInvocation invoke]中导致崩溃的寄存器

但是,当其中一个故障异常发生(并吞下它)时,调用后会发生崩溃返回[NSInvocation invoke]。这是一个坏的内存访问中R10其中根据GDB一个成功的跑分提领该值其中之一时:

(gdb) x 0x38388348 
0x38388348 <OBJC_IVAR_$_NSInvocation._retdata>:  0x00000008 

如果故障出现异常0x02的值处于引起崩溃的寄存器。

快速谷歌搜索告诉我,应该由被调用者保存r10,这意味着它不会被任何代码在发生此异常时进行更改。

有人可以解释一下吗?我不是专家,当涉及到这些低级细节

回答

0

我想你是在问错误的问题。 Cocoa应用程序在正常操作下不应抛出异常。在做其他事情之前,你需要解决这个异常的原因。

您不应该从多个线程访问单个托管对象上下文,或者您需要非常小心地锁定它。多线程访问一个上下文非常危险,并且可能导致您正在观察的行为。从核心数据编程指南的"Multi-Threading with Core Data"部分:

如果你想在不同的线程管理 对象的工作,你 必须锁定它的上下文(见NSLocking)。 如果试图通过实际的对象,线程之间 共享环境,以及,你必须非常小心 有关锁定(并因此 你很可能会抵消任何好处 所以 否则可能会从 多派生线程)。因此,跨越不同 线程 管理对象的工作是强烈 气馁,如“一般 准则。”

建议您使用一个单独的管理对象上下文的后台线程(具有相同持久性存储和托管对象模型),并在那里进行求和操作所需的所有读取。

+0

我确实使用了单独的上下文,并且唯一的解决方法是在尝试访问成员之前检查objectID是否存在。但即使这样也不完美。 – 2010-06-16 07:43:21

+0

@Mike Weller - 如果我正确理解了你,你已经为后台操作创建了一个单独的托管对象上下文,但是当你试图从持久存储中对某些托管对象进行错误处理时会收到异常,因为它们已被删除在将这些更改写入磁盘的单独上下文中。在这种情况下,您需要确保您的后台上下文协调更改,如下所述:http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/CoreData/Articles/cdChangeManagement.html# // apple_ref/doc/uid/TP30001201-CJBDBHCB – 2010-06-16 17:30:51

+0

我熟悉冲突解决方案。问题是当操作获取对象时,它们显然都存在。有很多对象并迭代它们并计算信息需要很长时间。 能够检测到从其他上下文中删除,并以某种方式删除对已删除对象的引用是不可能的操作。我目前的解决方法只是在访问对象上的成员之前检查[context existingObjectWithID:]的结果。如果该项目已被删除,则返回nil。理论上这是“种族”,但在实践中应该没问题。 – 2010-06-17 10:35:48