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 次 |
最近记录: |