使用dispatch_async时EXC_BAD_ACCESS

时间:2017-05-01 07:16:51

标签: ios grand-central-dispatch exc-bad-access dispatch dispatch-async

我们最近修改了我们的线程机制,支持在大多数地方使用dispatch_async(在做了很多关于NSOperation和dispatch_async的阅读之后)*。然后我们的代码开始在代码的各个部分与EXC_BAD_ACCESS崩溃,总是在dispatch_async(queue,...)部分,没有明确的模式。通常在20分钟后发生--2小时。

我们的dispatch_async块用于通知侦听器,如下所示:

NSMutableSet *_listeners; // Initialised elsewhere and filled with interested listeners
void(^block)(id listener); // Block to execute

@synchronized(_listeners) {
  for (id listener in _listeners) {
    dispatch_async_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // We used different queues for different listeners, but showing only one type of queue here for brevity
    dispatch_async(queue, ^{ // CRASHING LINE
      block(listener);
    });
  }
}

常见的症状是:

  • 发生在iOS10上,从未在iOS8上发生
  • 在调试期间发生但从未报告过生产

(这是一个自我回答的问题)

*我们喜欢dispatch_async的简单性,不需要NSOperationQueue的阻塞/依赖功能,我们很快就会转向C ++,所以希望保持低水平。

1 个答案:

答案 0 :(得分:5)

经过几天的调试,确保我们的线程对象得到了强有力的保留,并尝试使用Instruments进行各种弱强组合和彻底的分析,我们得出结论这是一个Apple bug (如也reported here)仅出现在最近的iOS版本上(对我们来说是iOS10,但我认为它会在libBacktraceRecording.dylib开始出现时出现在该版本中。)

症状:

  • 在iOS8.x上无法重现
  • 仅在处于调试模式时才会发生
  • EXC_BAD_ACCESS代码的随机部分,没有任何模式

可能表示这一点。

希望这对其他人有用!