dispatch_semaphore_t aSemaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(aSemaphore, DISPATCH_TIME_FOREVER);
dispatch_release(aSemaphore);

当程序运行到 dispatch_release(aSemaphore)时,将导致“EXC_BAD_INSTRUCTION”,然后崩溃。为什么?

最佳答案

我尝试了这段代码,但确实由于非法指令而死亡。所以我做了一些挖掘,发现它在_dispatch_semaphore_dispose中快要消失了。因此,让我们看一下这是什么(这里是ARMv7,因为它很容易理解!):

__dispatch_semaphore_dispose:
000040a0            b590        push    {r4, r7, lr}
000040a2            4604        mov     r4, r0
000040a4            af01        add     r7, sp, #4
000040a6        e9d40108        ldrd    r0, r1, [r4, #32]
000040aa            4288        cmp     r0, r1
000040ac            da00        bge.n   0x40b0
000040ae            defe        trap
...

它死于0x40ae,这是放置在其中的duff指令,因此如果bge.n不使我们跳转到该分支时崩溃,则它将崩溃。

之所以失败,是因为r0必须小于r1r0r1是从r4 + 32的内存中加载的,该内存已经在堆栈中重新计算出来了,我认为r4在示例代码中就是aSemaphore,即传递给dispatch_semaphore_release的东西。 + 32表示它正在向aSemaphore指向的结构中读取32个字节(这是dispatch_semaphore_s结构的指针)。因此,总的来说,它的工作是从aSemaphore + 32读取4个字节并将其放入r0,然后从aSemaphore + 36读取4个字节并将其放入r1

然后,该比较有效地比较了aSemaphore + 32aSemaphore + 36的值。阅读什么dispatch_semaphore_create后,我可以看到它存储了传递给aSemaphore + 32aSemaphore + 36的值。我还发现dispatch_semaphore_waitdispatch_semaphore_signal触及aSemaphore + 32的值,以增加和减少它。这意味着它被破坏的原因是因为该信号量的当前值小于传递给dispatch_semaphore_create的值。因此,当当前值小于其创建时的值时,您将无法处理信号灯。

如果您已阅读这里并理解了我的杂谈,那就干得好!希望能帮助到你!

更新:

最好在这里查看源代码(由JustSid指出)-http://opensource.apple.com/source/libdispatch/libdispatch-187.7/src/semaphore.c-查看我们看到的_dispatch_semaphore_dispose函数:
if (dsema->dsema_value < dsema->dsema_orig) {
    DISPATCH_CLIENT_CRASH("Semaphore/group object deallocated while in use");
}

所以,是的,您去了,这就是为什么它崩溃的原因!

关于iphone - 为什么此代码会导致 “EXC_BAD_INSTRUCTION”?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8287621/

10-11 14:27