Boo*_*oon 40 exception objective-c grand-central-dispatch ios
我在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
});
});
Run Code Online (Sandbox Code Playgroud)
332*_*329 42
从堆栈跟踪中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或以下的ivar dispatch_semaphore_t.
我有一个不同的问题让我想到了这个问题,这个问题可能比接受的答案中的过度发布问题更常见.
根本原因是我们的完成块由于网络处理程序中的错误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);
}];
Run Code Online (Sandbox Code Playgroud)
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小组成对配对.
有时,获取 aEXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)所需要的只是缺少一个return语句。
这当然是我的情况。
| 归档时间: |
|
| 查看次数: |
88725 次 |
| 最近记录: |