【问题标题】:Cannot track down [NSData getBytes:length:] crash无法追踪 [NSData getBytes:length:] 崩溃
【发布时间】:2015-03-09 19:01:49
【问题描述】:

我在 Foundation 的 -[NSData(NSData) getBytes:length:] 方法中遇到了一个奇怪的 EXC_BAD_ACCESS 崩溃。它经常发生,但我无法从堆栈跟踪中获取任何有意义的信息。除了开源库(SDWebImage 中的一个和SocketRocket 中的一个)之外,我的代码中没有对 getBytes:length: 的调用,但似乎它们不会导致崩溃。

唯一的提示是崩溃发生在com.apple.CFNetwork.addPersistCacheToStorageDaemon 线程内,但我不知道它是怎么回事。有人可以帮忙吗?

来自 Crashlytics 的堆栈跟踪:

Thread : Crashed: com.apple.CFNetwork.addPersistCacheToStorageDaemon
0  libsystem_platform.dylib       0x3044a208 _platform_memmove$VARIANT$CortexA9 + 160
1  Foundation                     0x22df9167 -[NSData(NSData) getBytes:length:] + 118
2  Foundation                     0x22df9167 -[NSData(NSData) getBytes:length:] + 118
3  Foundation                     0x22e21a1b -[NSData(NSData) replacementObjectForCoder:] + 134
4  Foundation                     0x22dc2aff -[NSXPCEncoder _replaceObject:] + 90
5  Foundation                     0x22e240dd -[NSXPCEncoder _encodeArrayOfObjects:forKey:] + 192
6  Foundation                     0x22e212ff -[NSDictionary(NSDictionary) encodeWithCoder:] + 922
7  Foundation                     0x22dc32c9 -[NSXPCEncoder _encodeObject:] + 604
8  Foundation                     0x22dc379d encodeInvocationArguments + 460
9  Foundation                     0x22dc3455 -[NSXPCEncoder encodeInvocation:] + 360
10 Foundation                     0x22dc32c9 -[NSXPCEncoder _encodeObject:] + 604
11 Foundation                     0x22dc2335 -[NSXPCConnection _sendInvocation:proxyNumber:remoteInterface:withErrorHandler:timeout:userInfo:] + 1860
12 Foundation                     0x22dd2823 -[NSXPCConnection _sendInvocation:proxyNumber:remoteInterface:withErrorHandler:] + 58
13 Foundation                     0x22dd27db -[_NSXPCDistantObjectWithError forwardInvocation:] + 114
14 CoreFoundation                 0x2217e831 ___forwarding___ + 352
15 CoreFoundation                 0x220afb88 _CF_forwarding_prep_0 + 24
16 CFNetwork                      0x21c52ac9 -[NSURLStorage_CacheClient addCachedResponseWithDictionary:key:] + 120
17 CFNetwork                      0x21c21e29 ___ZN12__CFURLCache23CreateAndStoreCacheNodeEP16__CFURLCacheNodePK20_CFCachedURLResponsePK10__CFStringPK13_CFURLRequestPKvbRb_block_invoke + 1576
18 libdispatch.dylib              0x302cf423 _dispatch_call_block_and_release + 10
19 libdispatch.dylib              0x302d95d9 _dispatch_queue_drain$VARIANT$mp + 948
20 libdispatch.dylib              0x302d90a9 _dispatch_queue_invoke$VARIANT$mp + 84
21 libdispatch.dylib              0x302db0d3 _dispatch_root_queue_drain + 330
22 libdispatch.dylib              0x302dc1fb _dispatch_worker_thread3 + 106
23 libsystem_pthread.dylib        0x3044ce25 _pthread_wqthread + 668

还有一个(发生频率较低):

Thread : Crashed: com.apple.CFNetwork.addPersistCacheToStorageDaemon
0  libsystem_platform.dylib       0x000000019344d300 _platform_memmove + 176
1  Foundation                     0x0000000182dfce18 -[NSData(NSData) getBytes:length:] + 172
2  Foundation                     0x0000000182dfce18 -[NSData(NSData) getBytes:length:] + 172
3  Foundation                     0x0000000182e2ae3c -[NSData(NSData) replacementObjectForCoder:] + 160
4  Foundation                     0x0000000182dbd320 -[NSXPCEncoder _replaceObject:] + 120
5  Foundation                     0x0000000182e2dac8 -[NSXPCEncoder _encodeArrayOfObjects:forKey:] + 256
6  Foundation                     0x0000000182e2a544 -[NSDictionary(NSDictionary) encodeWithCoder:] + 1016
7  Foundation                     0x0000000182dbdd10 -[NSXPCEncoder _encodeObject:] + 716
8  Foundation                     0x0000000182dbe2e8 encodeInvocationArguments + 508
9  Foundation                     0x0000000182dbdee4 -[NSXPCEncoder encodeInvocation:] + 412
10 Foundation                     0x0000000182dbdd10 -[NSXPCEncoder _encodeObject:] + 716
11 Foundation                     0x0000000182dbcb0c -[NSXPCConnection _sendInvocation:proxyNumber:remoteInterface:withErrorHandler:timeout:userInfo:] + 2196
12 CoreFoundation                 0x0000000181fde230 ___forwarding___ + 440
13 CoreFoundation                 0x0000000181ee2b6c _CF_forwarding_prep_0 + 92
14 CFNetwork                      0x000000018199c908 ___ZN12__CFURLCache23CreateAndStoreCacheNodeEP16__CFURLCacheNodePK20_CFCachedURLResponsePK10__CFStringPK13_CFURLRequestPKvbRb_block_invoke + 1976
15 libdispatch.dylib              0x00000001932793ac _dispatch_call_block_and_release + 24
16 libdispatch.dylib              0x000000019327936c _dispatch_client_callout + 16
17 libdispatch.dylib              0x00000001932834c0 _dispatch_queue_drain + 1216
18 libdispatch.dylib              0x000000019327c474 _dispatch_queue_invoke + 132
19 libdispatch.dylib              0x0000000193285224 _dispatch_root_queue_drain + 664
20 libdispatch.dylib              0x000000019328675c _dispatch_worker_thread3 + 108
21 libsystem_pthread.dylib        0x00000001934552e4 _pthread_wqthread + 816

【问题讨论】:

  • 开发环境会出现这种情况吗?
  • @Zaph:不,我自己无法复制它。仅在生产中发生。
  • 大概getData 被传递了一个虚假的缓冲区地址,但很难猜测谁会负责。请注意,这两种情况都涉及对 URL 缓存的操作。
  • 我也经历过同样的崩溃。无法重现,因为它是由 Crashlytics 报告的。它发生在 SDWebImage 中。
  • 我在 Crashlytics 中也经常看到此崩溃,但从未能够重现它。该应用程序还使用 SDWebImage,但我不确定这是否相关。

标签: ios objective-c crash nsdata exc-bad-access


【解决方案1】:

随着 iOS 8 的推出,也发生了一些意想不到的错误,我们也必须牢记这一点。

像 MIT Mobile、Mile point 这样的应用程序也遇到了像你这样的问题,虽然目前还没有广泛传播。

这里是MITMilePoint 的错误链接。

com.apple.CFNetwork.addPersistCacheToStorageDaemon

CFNetwork 是较低级别的 C API,它由更高级别的类(如 NSURLConnection)包装。

所以崩溃发生在网络操作期间

EXC_BAD_ACCESS

这意味着消息被发送到一个没有类实例来执行它的内存地址。因此导致“访问不正确”

什么时候会发生?

  1. 对象未初始化
  2. 一个对象已经被释放了
  3. 其他不太可能发生的事情

我们该如何解决这个问题?

  • 您可以通过在 xcode 中启用 NSZombie 来捕获一些错误(编号 2)

启用 NSZombie:

启用此功能后,每个已释放对象的位置都会保留一个虚拟对象(僵尸),从而允许调试已释放的对象。非常容易启用:

  1. 在 XCode 的“可执行文件”中双击你的可执行文件
  2. 在“要在环境中设置的变量”中打开“参数”选项卡(这是底部的列表,请注意您编辑的是哪个)
  3. 单击“+”按钮,变量名称输入“NSZombieEnabled”,值“YES”

现在,您不必想知道发生了什么以及究竟是哪个对象产生了问题,而是确切地看到哪个类是麻烦制造者,并且您会很快调试它。

注意: 当您将应用程序提交到 App Store 时,不要让僵尸程序处于启用状态。此外,如果您真的不需要它们,最好禁用它们。

  • 如果您使用第三方库,请将其更新到最新版本

注意:

我的建议是永远不要使用第三方框架,除非这是不可避免的,因为库本身有时会出现不受开发人员控制的错误,有时库会更新到当前的 SDK。您可以找到更多关于它的信息here

希望对你有帮助

【讨论】:

    【解决方案2】:

    我猜你有

    • 一些__unsafe_unretained(即unavoidable用于设置器路径 [NSInvocation setArgument:atIndex:])
    • 或类似this one 的问题
    • 或(更有可能deadlockperformBlockAndWait 期间 (因为我在堆栈中看到了连接/超时)

    一些相关的建议:

    1) NSManagedObjectNSManagedObjectContextNSPersistentStoreCoordinator(鉴于 addPersistCacheToStorageDaemon 的崩溃)不是线程安全的:

    • 如果您使用performBlockAndWait 发送消息,请考虑这一点 到您的NSManagedObjectContext(更多herehere)或 nested MOC

    2) CFNetwork 是由NSURLConnection 包装的低级类:

    • 所以不使用NSURL?避免addObserver:self forKeyPath (KVO) 到 NSURL 会话的属性?

    【讨论】:

      【解决方案3】:

      问题实际上可能来自 SDWebImage 引自本站:

      http://webcache.googleusercontent.com/search?q=cache:BCShJT0ZrvoJ:quabr.com/15786084/uicollectionview-bad-acces-on-uicollectionviewdata-setlayoutattributesatglo+&cd=7&hl=fr&ct=clnk&gl=jp

      现在,如果您使用 AFNetworking 直接从使用 AFNetworking 类别的 URL 设置图像,您可能需要使用替代方法,以便您可以干预和调整图像大小。下面的代码会做到这一点。

      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:imageURL];
      [request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
      
      [imageView setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
          // resize image
          // set image on imageView
      } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
          // handle error
      }];
      

      我还会检查此页面是否有相关的崩溃:

      https://github.com/rs/SDWebImage/issues?q=is%3Aopen+is%3Aissue+label%3Acrash

      检查您是否使用最新版本的 SDWebImage,否则您可能需要检查旧问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-12
        • 2021-09-30
        • 1970-01-01
        • 2011-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-08
        相关资源
        最近更新 更多