我在dispatch_semaphore_dispose上收到EXC_BAD_指令(代码=EXC_I386_INVOP,子代码=0x0),但我真的不知道如何追踪这一问题的根本原因.我的代码使用了dispatch\u async、dispatch\u group\u enter等等.

更新:

在此处输入图像描述

代码:

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 (code=EXC_I386_INVOP, subcode=0x0)是因为101 was released while it was still locking (waiting for 102).

根据你的发现,事情就是这样的:

  • 创建了dispatch_group_t group个.101's retain count = 1.
  • -[self webservice:onCompletion:]人占领了group人.101's retain count = 2.
  • dispatch_async(...., ^{ dispatch_group_wait(group, ...) ... });再次占领了group.101's retain count = 3.
  • 退出当前作用域.group人获释.100's retain count = 2.
  • dispatch_group_leave人从未被叫来.
  • dispatch_group_wait是超时.dispatch_async街区已经完工.group人获释.102's retain count = 1.
  • 你又调用了这个方法.当再次调用-[self webservice:onCompletion:]时,旧的onCompletion块被替换为新的.所以,旧的group被释放了.102's retain count = 0. group被解除分配.结果是EXC_BAD_INSTRUCTION人.

To fix this, I suggest you should find out why 100 didn't call 101 block, and fix it. Then make sure the next call to the method will happen after the previous call did finish.


如果您允许多次调用该方法,无论之前的调用是否完成,您可能会找到一个人为您保留group次:

  • 您可以将超时时间从2秒更改为DISPATCH_TIME_FOREVER秒,或者更改为所有-[self webservice:onCompletion]个模块在该时间之前调用其onCompletion个模块的合理时间.这样dispatch_async(...)号街区就能为你保留它
  • 可以向集合中添加group,例如NSMutableArray.

我想是the best approach to create a dedicate class for this action.当你想调用webservice时,你需要创建一个类的对象,调用该类上的方法,并将完成块传递给它,从而释放该对象.在课堂上,ivar为dispatch_group_tdispatch_semaphore_t.

Objective-c相关问答推荐

NSNumberFormatter 和 'th' 'st' 'nd' 'rd' (序数)数字结尾

iOS8:退出应用程序后不久出现蓝条正在使用您的位置

NSBundle pathForResource 为 NULL

如何在运行时向对象添加属性?

在 ARC 之后,我应该为调度队列使用什么属性?

Objective C - 为什么常量以 k 开头

Objective C const NSString * vs NSString * const

使用 UIView animateWithDuration 进行动画处理时无法 UIButton

在 NSMutableArray 的开头添加一个对象?

了解按位与运算符

将 HTTP 标头添加到 NSURLRequest

UIBezierPath 减go 路径

iOS Buttons - 添加边框

遍历 NSString 中所有字符的最有效方法

如何设置 NSPredicate 来查找具有 nil 属性的对象

Objective-C中的继承和类别有什么区别

选中时选中的 UItableViewCell 保持蓝色

如何修复UIPopoverController 已弃用警告?

iOS 10 中的错误:无法从 https://mesu.apple.com/assets/ 复制assets资源信息以获取assets资源类型

NSNumber 和 NSInteger 有什么区别?