我在dispatch_semaphore_dispose上获得了EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0),但实际上并不知道如何找到这个的根本原因。我的代码使用了dispatch_async,dispatch_group_enter等。
更新: 崩溃的原因是因为webserviceCall(请参阅下面的代码)从不调用onCompletion,当代码再次运行时,我收到错误EXC_BAD_INSTRUCTION。我确认情况确实如此,但不确定为什么或如何防止这种情况。
代码:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t group = dispatch_group_create();
for (...) {
if (...) {
dispatch_group_enter(group);
dispatch_async(queue, ^{
[self webserviceCall:url onCompletion:^{
dispatch_group_leave(group);
}];
});
}
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
dispatch_sync(queue, ^{
// call completion handler passed in by caller
});
});
答案 0 :(得分:40)
从您的堆栈跟踪中发现EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
,因为 dispatch_group_t
在仍然锁定(等待dispatch_group_leave
)时被释放。
根据你的发现,这就是发生的事情:
dispatch_group_t group
已创建。 group
的保留计数= 1。 -[self webservice:onCompletion:]
抓获了group
。 group
的保留计数= 2。 dispatch_async(...., ^{ dispatch_group_wait(group, ...) ... });
再次抓获group
。 group
的保留计数= 3。 group
已被释放。 group
的保留计数= 2。 dispatch_group_leave
从未被召唤过。dispatch_group_wait
超时。 dispatch_async
块已完成。 group
已被释放。 group
的保留计数= 1。 -[self webservice:onCompletion:]
时,旧onCompletion
块将替换为新块。所以,旧的group
被释放了。 group
的保留计数= 0。 group
已取消分配。结果是EXC_BAD_INSTRUCTION
。 要解决此问题,我建议你应该找出为什么-[self webservice:onCompletion:]
没有调用onCompletion
阻止并修复它。然后确保在上一次调用完成后,下一次调用该方法。
如果您允许多次调用该方法,无论之前的调用是否完成,您可能会找到某人为您保留group
:
DISPATCH_TIME_FOREVER
或将所有-[self webservice:onCompletion]
按时间调用onCompletion
块的合理时间更改。因此dispatch_async(...)
中的区块会为您保留。group
添加到集合中,例如NSMutableArray
。我认为是为此操作创建专用类的最佳方法。当你想调用 webservice 时,你就创建了一个类的对象,调用它上面的方法,并将完成块传递给它,它将释放该对象。在课堂上,有一个dispatch_group_t
或dispatch_semaphore_t
的ivar。
答案 1 :(得分:7)
我的问题是REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
Image_Name latest d8dcd701981e About an hour ago 6.565 GB
,但没有与界面构建器连接并在swift文件中使用。
答案 2 :(得分:5)
我有一个不同的问题让我想到了这个问题,这个问题可能比接受答案中的过度发布问题更常见。
根本原因是我们的完成块被称为两次,因为网络处理程序中的if / else掉落不好,导致每次调用dispatch_group_leave
两次dispatch_group_enter
}。
dispatch_group_enter(group);
[self badMethodThatCallsMULTIPLECompletions:^(NSString *completion) {
// this block is called multiple times
// one `enter` but multiple `leave`
dispatch_group_leave(group);
}];
count
在EXC_BAD_INSTRUCTION
后,您仍然可以在调试器中访问dispatch_group。打印出dispatch_group,你会看到:
<OS_dispatch_group: group[0x60800008bf40] = { xrefcnt = 0x2, refcnt = 0x1, port = 0x0, count = -1, waiters = 0 }>
当您看到count = -1
时,它表示您已经超越了dispatch_group。请务必将dispatch_enter
和dispatch_leave
组配对。
答案 3 :(得分:4)
我的问题是我正在创建我希望存储在NSMutableDictionary中的对象,但我从未初始化字典。因此,对象被垃圾收集删除并在以后中断。检查您是否至少有一个对您正在与之交互的对象的强引用。
答案 4 :(得分:1)
就我而言:
PHImageRequestOptions *requestOptions = [PHImageRequestOptions new];
requestOptions.synchronous = NO;
尝试使用dispatch_group执行此操作
答案 5 :(得分:1)
有时,获取EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
所需的只是缺少return
语句。
这当然是我的理由。
答案 6 :(得分:0)
由于XCTestCase,我在这里登陆,其中我通过在no_testBackgroundAdding中使用'no_'作为前缀来禁用大多数测试。一旦我注意到大多数答案与锁和线程有关,我意识到测试包含一些XCTestExpectation实例和相应的waitForExpectations。他们都在禁用测试中,但显然Xcode仍然在某种程度上评估它们。
最后我发现XCTestExpectation被定义为@property但缺少@synthesize。一旦我添加了synthesize指令,EXC_BAD_INSTRUCTION就消失了。
答案 7 :(得分:0)
我的问题是它在我的init()中。 初始化未完成时,“弱者”可能杀死了他。 我将其从init中移出,它解决了我的问题。