ios - __destroy_helper_block_ 上的 Objective-C 崩溃

标签 ios objective-c objective-c-blocks

我有一个 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/

相关文章:

ios - 使用 resizableImageWithCapInsets 将拉伸(stretch)的 UIImage 设置为 UILabel 的背景

ios - 更改UILabel的第一行颜色

ios - UISplitViewController - 在主视图 Controller 中点击单元格会导致在主视图 Controller 中出现 segue,而不是在详细 View Controller 中

iphone - ‘id’类型对象转NSArray问题

ios - 如何将字典值放入数组?

iphone - 尝试了解 iOS 上的 block

ios - block 中自身的引用计数

CGAffineTransform 做等距变换的 iPhone iOS [ _ ] 到/_/

ios - UIImage initWithContentsOfFile 为空

javascript - 异步实际上是如何工作的......?