dispatch_semaphore_dispose上的EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0) [英] EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) on dispatch_semaphore_dispose
问题描述
我在dispatch_semaphore_dispose上获得EXC_BAD_INSTRUCTION(code = EXC_I386_INVOP,子代码= 0x0),但是并不知道如何追踪这个的根本原因。我的代码使用dispatch_async,dispatch_group_enter等。
I am getting EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) on dispatch_semaphore_dispose but don't really know how to track down the root cause of this. My code makes use of dispatch_async, dispatch_group_enter and so on.
更新:
崩溃的原因是由于webserviceCall(见下面的代码) )永远不会调用onCompletion,当代码再次运行时,我收到错误EXC_BAD_INSTRUCTION。我确认这是事实,但不知道为什么或如何防止这种情况。
UPDATE: The cause of the crash is due to the fact that the webserviceCall (see code below) never calls onCompletion and when the code is run again, I got the error EXC_BAD_INSTRUCTION. I verified this is indeed the case, but not sure why or how to prevent this.
代码:
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
});
});
推荐答案
从您的堆栈跟踪,发生EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)
,因为 dispatch_group_t
在它仍然锁定时发布(等待 dispatch_group_leave
)。
From your stack trace, EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
occurred because dispatch_group_t
was released while it was still locking (waiting for dispatch_group_leave
).
根据您发现的情况,发生这种情况:
According to what you found, this was what happened :
-
dispatch_group_t group
已创建。组
的保留计数= 1。 -
- [self webservice: onCompletion:]
捕获组
。组
的保留计数= 2。 -
dispatch_async 。,^ {dispatch_group_wait(group,...)...});
再次捕获组
。组
的保留计数= 3。 - 退出当前范围。
组
已发布。组
的保留计数= 2。 -
dispatch_group_leave
从未被调用。 -
dispatch_group_wait
已超时。dispatch_async
块已完成。组
已发布。组
的保留计数= 1。 - 您再次调用了此方法。当
- [self webservice:onCompletion:]
再次被调用时,旧的onCompletion
块被替换为新的。所以,旧的组
被发布。组
的保留计数= 0。组
被取消分配。这导致EXC_BAD_INSTRUCTION
。
dispatch_group_t group
was created.group
's retain count = 1.-[self webservice:onCompletion:]
captured thegroup
.group
's retain count = 2.dispatch_async(...., ^{ dispatch_group_wait(group, ...) ... });
captured thegroup
again.group
's retain count = 3.- Exit the current scope.
group
was released.group
's retain count = 2. dispatch_group_leave
was never called.dispatch_group_wait
was timeout. Thedispatch_async
block was completed.group
was released.group
's retain count = 1.- You called this method again. When
-[self webservice:onCompletion:]
was called again, the oldonCompletion
block was replaced with the new one. So, the oldgroup
was released.group
's retain count = 0.group
was deallocated. That resulted toEXC_BAD_INSTRUCTION
.
为了解决这个问题,我建议你应该找出为什么 - [self webservice:onCompletion:]
没有调用$ code> onCompletion 块,并修复它。然后确保下一次调用该方法将在上一次调用完成后发生。
To fix this, I suggest you should find out why -[self webservice:onCompletion:]
didn't call onCompletion
block, and fix it. Then make sure the next call to the method will happen after the previous call did finish.
如果您允许多次调用该方法,无论以前的呼叫是否完成,您可能会发现有人为您持有组
:
In case you allow the method to be called many times whether the previous calls did finish or not, you might find someone to hold group
for you :
- 您可以将超时从2秒更改为
DISPATCH_TIME_FOREVER
或合理的时间,所有- [self webservice:onCompletion]
应该调用他们的onCompletion
块。因此,dispatch_async(...)
中的块将保留给您。
OR - 您可以将
group
添加到集合中,例如NSMutableArray
。
- You can change the timeout from 2 seconds to
DISPATCH_TIME_FOREVER
or a reasonable amount of time that all-[self webservice:onCompletion]
should call theironCompletion
blocks by the time. So that the block indispatch_async(...)
will hold it for you.
OR - You can add
group
into a collection, such asNSMutableArray
.
我认为这是为这个动作创建一个专用类的最佳方法。当您想要调用 webservice 时,您将创建一个类的对象,调用其上的方法,并将传递给完成块的方法释放该对象。在课堂上,有一个ivar的 dispatch_group_t
或 dispatch_semaphore_t
。
I think it is the best approach to create a dedicate class for this action. When you want to make calls to webservice, you then create an object of the class, call the method on it with the completion block passing to it that will release the object. In the class, there is an ivar of dispatch_group_t
or dispatch_semaphore_t
.
这篇关于dispatch_semaphore_dispose上的EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!