在曲棍球应用仪表板中,出现以下提示崩溃:
异常类型:SIGTRAP 异常代码:#0 at 0x1943f61e8 损坏的线程数:7 特定于应用程序的信息: 在当前参数寄存器中找到的选择器名称:保留
异常类型:SIGSEGV 异常代码:SEGV_ACCERR at 0x568855a90 损坏的线程数:18 特定于应用程序的信息: objc_msgSend()选择器名称:保留
两个崩溃组都使用相同的代码,但是它们以某种方式具有不同的崩溃描述,我认为这应该是相同的根本原因。
这是我的代码的样子:
线程1:
@synchronized (self) {
_mySerialQueue = dispatch_queue_create(...);
}
线程2:
{{1}}
此代码能否遇到ARC问题?
答案 0 :(得分:1)
(请验证这些前提)
_mySerialQueue
是一个实例变量_mySerialQueue
仅在@synchronized(self)
个块内访问_mySerialQueue
)访问[theObject valueForKey:"mySerialQueue"]
我只看到上述代码可能崩溃的原因之一。我仍然不确定100%,但这是我的镜头:
崩溃发生时, self
正在被释放。可以检查是否清洁了dealloc
中的iVar:
- (void)dealloc {
@synchronized(self) {
_mySerialQueue = nil;
}
// ...
}
这些崩溃非常罕见,例如至少一百分之一。如果这种情况经常发生,我认为问题出在其他地方。
更改后,应用程序仍然会崩溃,但是EXC_BAD_ACCESS将位于较低的内存位置,因为调用dispatch_async(nil, ...)
时将取消引用NULL指针。崩溃位置很可能是0x00000050或类似的低地址。
我为什么这么认为?
销毁对象时,iVar将通过名为.cxx_destruct
的方法单独销毁。发生这种情况时,iVar可能正在被释放,但是同时该变量仍指向该对象,因为它从未被清除。
重要提示:如果该方法可行,它将用另一种罕见的崩溃替换一种罕见的崩溃,因为这意味着self
上存在竞争条件。
另一种可能的解决方案是尝试使用线程清理器重现该问题。在大多数情况下,它可以非常迅速地找到此类问题。