我有一个 iOS 应用程序在调用 __destroy_helper_block_253
和 __destroy_helper_block_278
时崩溃,我不确定“destroy_helper_block”引用的是什么或者它后面的数字是什么应该指向。
有没有人对如何追踪这些崩溃可能发生的确切位置有任何指示?
这是一个回溯示例(请注意,带有 __destroy_helper_block
的行仅引用它所在的文件,而通常情况下行号也会包含在内)。
Thread : Crashed: com.apple.root.default-priority
0 libdispatch.dylib 0x000000018fe0eb2c _dispatch_semaphore_dispose + 60
1 libdispatch.dylib 0x000000018fe0e928 _dispatch_dispose + 56
2 libdispatch.dylib 0x000000018fe0e928 _dispatch_dispose + 56
3 libdispatch.dylib 0x000000018fe0c10c -[OS_dispatch_object _xref_dispose] + 60
4 Example App 0x00000001000fe5a4 __destroy_helper_block_278 (TSExampleApp.m)
5 libsystem_blocks.dylib 0x000000018fe53908 _Block_release + 256
6 Example App 0x00000001000fda18 __destroy_helper_block_253 (TSExampleApp.m)
7 libsystem_blocks.dylib 0x000000018fe53908 _Block_release + 256
8 libdispatch.dylib 0x000000018fe0bfd4 _dispatch_client_callout + 16
9 libdispatch.dylib 0x000000018fe132b8 _dispatch_root_queue_drain + 556
10 libdispatch.dylib 0x000000018fe134fc _dispatch_worker_thread2 + 76
11 libsystem_pthread.dylib 0x000000018ffa16bc _pthread_wqthread + 356
编辑 1:这是发生崩溃的文件中定义的 block 之一的示例(删除了特定于应用程序的代码)。
- (void)doSomethingWithCompletion:(void (^)())completion {
void (^ExampleBlock)(NSString *) = ^{
NSNotification *notification = [NSNotification notificationWithName:kExampleNotificationName object:nil userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotification:notification];
if (completion) {
completion();
}
};
// Async network call that calls ExampleBlock on either success or failure below...
}
文件中还有许多其他 block ,但其中大部分是作为参数提供给方法的,而不是先定义然后再引用。
编辑 2:为上述函数添加了更多上下文。
最佳答案
堆栈跟踪的每一帧都应该为您提供有关 libDispatch 正在做什么导致崩溃的线索。从底部开始工作:
11 libsystem_pthread.dylib 0x000000018ffa16bc _pthread_wqthread
10 libdispatch.dylib 0x000000018fe134fc _dispatch_worker_thread2 + 76
这两个函数启动一个工作线程并运行它。在此过程中,它还为线程设置了一个自动释放池。
9 libdispatch.dylib 0x000000018fe132b8 _dispatch_root_queue_drain + 556
此函数表示队列销毁过程的开始。特定于线程的自动释放池被耗尽,并且在该过程中释放该特定队列引用的所有变量。因为这是 libDispatch,这意味着底层的 mach 对象和您提交的工作 block 必须离开......
7 libsystem_blocks.dylib 0x000000018fe53908 _Block_release + 256
6 Example App 0x00000001000fda18 __destroy_helper_block_253 (TSExampleApp.m)
5 libsystem_blocks.dylib 0x000000018fe53908 _Block_release + 25
4 Example App 0x00000001000fe5a4 __destroy_helper_block_278 (TSExampleApp.m)
这正是这里发生的事情。数字 7 是外部 block ,因为它包含一个要销毁的非平凡对象(又是另一个 block ),编译器生成了一个析构函数 (__destroy_helper_block_253
) 来摆脱那个内部 block 。应用相同的逻辑,我们可以推断出内部 block 还有一点重要的破坏要做。
3 libdispatch.dylib 0x000000018fe0c10c -[OS_dispatch_object _xref_dispose] + 60
2 libdispatch.dylib 0x000000018fe0e928 _dispatch_dispose + 56
1 libdispatch.dylib 0x000000018fe0e928 _dispatch_dispose + 56
这些台词是你所有烦恼的根源。出于某种原因,您已经捕获了您正在回调的队列,或者您已经捕获了一个对象,该对象持有对队列的引用很弱,这样当它走恐龙的路时,它会带走它的队列.这会导致 libDispatch 假定队列已完成,并且它会继续解除分配,直到它到达特定于信号量的处置
0 libdispatch.dylib 0x000000018fe0eb2c _dispatch_semaphore_dispose + 60
由于没有要释放的信号量,mach 会提示到在信号量销毁时不返回 KERN_SUCCESS
,这是 libDispatch 中的 fatal error 。事实上,在这种情况下它会 abort()
- 嗯,技术上是 __builtin_trap()
,但它们实现了相同的目标。因为没有附加调试器,所以您的应用会停止运行。
所以这就提出了一个问题:你如何解决这个问题?好吧,首先你需要找到什么,如果有的话引用了一个调度对象。你提到你正在做一些异步网络,所以那将是首先检查的地方。如果这些对象中的任何一个碰巧持有一个队列或信号量,或者引用一个持有队列或信号量的对象,并且您没有在任何这些 block 中强烈捕获它,那么当 block 与对象一起超出范围时,就会发生这种情况.
关于ios - __destroy_helper_block_ 上的 Objective-C 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23573114/