EXC_BAD_ACCESS 使用 dispatch_async 时

EXC_BAD_ACCESS when using 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);
    });
  }
}

y 的常见症状是:

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

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

经过几天的调试,确保我们的线程对象被强烈保留,并尝试各种弱-强组合并使用 Instruments 进行彻底的分析,我们得出的结论是 这是一个 Apple 错误(还有 ),只出现在最近的 iOS 版本中(对我们来说是 iOS10,但我认为它会在 libBacktraceRecording.dylib 开始时的版本中出现出现)。

以下症状:

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

可能表明这一点。

希望这对其他人有用!