Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS崩溃-在当前参数寄存器中找到选择器名称:retain_Ios_Objective C_Iphone_Automatic Ref Counting_Grand Central Dispatch - Fatal编程技术网

iOS崩溃-在当前参数寄存器中找到选择器名称:retain

iOS崩溃-在当前参数寄存器中找到选择器名称:retain,ios,objective-c,iphone,automatic-ref-counting,grand-central-dispatch,Ios,Objective C,Iphone,Automatic Ref Counting,Grand Central Dispatch,在曲棍球应用程序仪表板中,我遇到了以下提示: 异常类型:SIGTRAP 异常代码:#0位于0x1943f61e8 崩溃线程:7 特定于应用程序的信息: 在当前参数寄存器中找到选择器名称:retain 异常类型:SIGSEGV 异常代码:0x568855a90处的SEGV_ACCERR 崩溃线程:18 特定于应用程序的信息: objc_msgSend()选择器名称:retain 两个崩溃组都使用相同的代码,但不知何故,它们有不同的崩溃描述,我认为这应该是相同的根本原因 这就是我的代码的样子: 线程

在曲棍球应用程序仪表板中,我遇到了以下提示:

异常类型:SIGTRAP 异常代码:#0位于0x1943f61e8 崩溃线程:7 特定于应用程序的信息: 在当前参数寄存器中找到选择器名称:retain

异常类型:SIGSEGV 异常代码:0x568855a90处的SEGV_ACCERR 崩溃线程:18 特定于应用程序的信息: objc_msgSend()选择器名称:retain

两个崩溃组都使用相同的代码,但不知何故,它们有不同的崩溃描述,我认为这应该是相同的根本原因

这就是我的代码的样子:

线程1:

dispatch_queue_t queue;
@synchronized (self) {
    queue = _mySerialQueue;
}
dispatch_async(queue, ^{ // Crash happens here
    if (_ivar) {
        ...
    }
});
线程2:

@synchronized (self) {
    _mySerialQueue = dispatch_queue_create(...);
}
此代码是否会遇到ARC问题

前提是(请验证这些)

  • \u mySerialQueue
    是一个实例变量
  • \u mySerialQueue
    仅在
    @同步(自)
    块内访问
  • 您不能通过任何属性或键值编码访问
    \u mySerialQueue
    [theObject valueForKey:“mySerialQueue”]
  • 您发布的所有代码都使用ARC运行
我只看到上面的代码会以这种方式崩溃的一个原因。我仍然不是100%确定,但这是我的照片:

当崩溃发生时,
self
正在解除分配过程中。如果在
dealloc
中清洁iVar,则可以检查:

-(无效)解除锁定{
@同步(自){
_mySerialQueue=nil;
}
// ...
}
这些事故极为罕见,例如至少百分之一的事故。如果这种情况发生得更频繁,我认为问题出在其他地方

更改后,应用程序仍将崩溃,但EXC\u BAD\u访问将位于较低的内存位置,因为调用
dispatch\u async(nil,…)
时取消了对空指针的引用。崩溃位置很可能是0x00000050,或类似的低地址

我为什么这么想? 销毁对象时,IVAR将通过名为
.cxx\u destruct
的方法在单独的过程中销毁。发生这种情况时,iVar可能处于解除分配过程中,但同时变量仍然指向对象,因为它从未被清除

重要提示:如果这样做有效,它只会用另一个罕见的崩溃取代一个罕见的崩溃,因为这意味着
self
上的某个地方存在竞争条件



另一个可能的解决方案是尝试用线程消毒剂重现问题。在大多数情况下,它可以非常快速地跟踪此类问题。

您是否保证线程1上的代码在线程2上的代码之后执行?崩溃是随机的吗?(其中“随机”表示偶尔发生一次,但不可重复?@bbum:如果不是,则
\u mySerialQueue
将是
nil
,而
[nil retain]
永远不会发生crashes@Michael是 啊但是dispatch_async(nil,…)是未定义的IIRC,并且,给定blocks运行时,可能有一条路径会导致[garbage retain]。@bbum:不,没有。我查看了程序集:)它只是在EXC_BAD_访问中崩溃,因为它试图取消对空指针的引用。然而,这个问题中的指针:0x1943f61e8指向一些iVar,0x568855a90指向一个对象(所有对象都是16字节对齐的,第一个指针不是16字节对齐的)。这是一个合理的推测。特别是,如果
self
表示某种工作对象,则需要在完成工作单元之前保持对
self
的强引用。未能做到这一点是并发模型崩溃的一个常见原因。您提出的前提在我的代码中得到了满足。你是对的,这次崩溃不容易重现。事情的发生就像@JayceeJiang:我想你可以试试“线程消毒剂”。(如果你在谷歌上搜索“ios线程消毒剂”,你会发现很多资源)。如果你玩几分钟你的应用程序,它可能会发现问题。如果这没有帮助,我会尝试“未定义的行为消毒剂”下一步。如果这对你没有帮助,你可以运行clang analyzer(Xcode菜单->产品->分析)。@JayceeJiang:还要注意的是,如果你还没有运行线程消毒剂,它可能会首先发现很多其他问题。修复所有这些可能需要几个小时。。(我去过那里。)