__destroy_helper_block_上的Objective-C崩溃 [英] Objective-C crash on __destroy_helper_block_

查看:3116
本文介绍了__destroy_helper_block_上的Objective-C崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个iOS应用程序在 __ destroy_helper_block_253 __ destroy_helper_block_278 等调用时崩溃,我不确定是什么或者destroy_helper_block正在引用或它应该指向的数字。

I have an iOS application that's crashing on calls like __destroy_helper_block_253 and __destroy_helper_block_278 and I'm not really sure what either "destroy_helper_block" is referencing or what the number after it is supposed to point to.

有没有人有任何关于如何追踪这些崩溃可能发生在哪里的指针?

Does anyone have any pointers for how to track down where exactly these crashes might be occuring?

这是一个示例回溯(请注意,带有 __ destroy_helper_block 的行仅引用它包含的文件而没有其他内容,通常也包括行号。)

Here's an example traceback (note that the lines with __destroy_helper_block only references the file it's contained in and nothing else, when normally the line number would be included as well).

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:以下是其中一个块定义的示例发生崩溃的文件(编辑出特定于应用程序的代码)。

Edit 1: Here's an example of one of the blocks defined in the file where the crash occurs (with application-specific code edited out).

- (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...
}

文件中还有许多其他块,但大多数块都是作为方法的参数提供的,而不是先定义,然后再引用。

There are many other blocks in the file, but most of them are provided as arguments to methods instead of being defined first and then referenced later.

编辑2:在上面的函数中添加了更多上下文。

Edit 2: Added more context to above function.

推荐答案

堆栈跟踪的每一帧都应该给你一个线索到libDispatch正在做什么导致崩溃。从底部开始工作:

Each frame of the stack trace should give you a clue as to what libDispatch is doing to cause the crash. Working our way from the bottom:

11 libsystem_pthread.dylib        0x000000018ffa16bc _pthread_wqthread
10 libdispatch.dylib              0x000000018fe134fc _dispatch_worker_thread2 + 76

这两个函数会启动一个工作线程并运行它。在此过程中,它还为线程设置了自动释放池。

These two functions spin up a worker thread and runs it. In the process, it also sets up an autorelease pool for the thread.

9  libdispatch.dylib              0x000000018fe132b8 _dispatch_root_queue_drain + 556

此函数表示队列销毁过程的开始。排除特定于线程的自动释放池,并且在该过程中释放该特定队列引用的所有变量。因为这是libDispatch,这意味着底层的mach对象和你提交的工作块必须去...

This function signals the start of the queue destruction process. The thread-specific autorelease pool is drained, and in the process all variables referenced by that particular queue are released. Because this is libDispatch, that means the underlying mach object and the work block you submitted have got to go...

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)

这正是这里发生的事情。 Number 7是外部块,因为它包含一个要销毁的非常重要的对象(还有另一个块),编译器生成了一个析构函数( __ destroy_helper_block_253 )来摆脱那个内部块。应用相同的逻辑线,我们可以推断出内部块还有另外一点非常重要的破坏。

which is precisely what happens here. Number 7 is the outer block and because it contains a nontrivial object to destroy (yet another block), the compiler generated a destructor (__destroy_helper_block_253) to get rid of that inner block too. Applying the same line of logic, we can deduce that the inner block has yet another bit of nontrivial destroying to do.

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假定队列已完成并且它一直处于dealloc'ing状态,直到它到达信号量特定的dispose

These lines are the root cause of all your troubles. For some reason, you've either captured the queue you're calling back on, or you've captured an object that holds a reference to a queue weakly such that when it goes the way of the dinosaur, it takes its queue with it. This causes libDispatch to assume the queue is done for and it keeps on dealloc'ing until it reaches the semaphore-specific dispose

0  libdispatch.dylib              0x000000018fe0eb2c _dispatch_semaphore_dispose + 60

没有信号量释放,马赫会抱怨不要返回 KERN_SUCCESS 关于信号量破坏,这是libDispatch中的致命错误。实际上,在这样的情况下它会 abort() - 技术上 __ builtin_trap(),但是他们完成了同样的目标。因为没有连接调试器,所以你的应用程序就会失效。

With no semaphore to release, mach will complain enough not to return KERN_SUCCESS on semaphore destruction, which is a fatal error in libDispatch. In fact, it will abort() in such a case -well, technically __builtin_trap(), but they accomplish the same goal. Because there's no debugger attached, down goes your app.

所以这引出了一个问题:你如何解决这个问题?好吧,首先你需要找到什么,如果有什么东西引用一个调度对象。你提到你正在做一些异步网络,所以这将是首先检查的地方。如果这些对象中的任何一个恰好拥有一个队列或信号量,或者引用一个对象,并且你没有在任何这些块中强烈捕获它,那么这正是当块与对象一起超出范围时会发生的情况。

So this raises the question then: how do you fix this? Well, first you need to find what, if anything is referencing a dispatch object. You mentioned that you were doing some asynchronous networking, so that would be the place to check first. If any of those objects happens to hold a queue or semaphore, or references an object that does, and you aren't capturing it strongly in any of those blocks, this is precisely what happens when the block passes out of scope along with the object.

这篇关于__destroy_helper_block_上的Objective-C崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆