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
必须小于r1
。 r0
和r1
是从r4 + 32
的内存中加载的,该内存已经在堆栈中重新计算出来了,我认为r4
在示例代码中就是aSemaphore
,即传递给dispatch_semaphore_release
的东西。 + 32
表示它正在向aSemaphore
指向的结构中读取32个字节(这是dispatch_semaphore_s
结构的指针)。因此,总的来说,它的工作是从aSemaphore + 32
读取4个字节并将其放入r0
,然后从aSemaphore + 36
读取4个字节并将其放入r1
。然后,该比较有效地比较了
aSemaphore + 32
和aSemaphore + 36
的值。阅读什么dispatch_semaphore_create
后,我可以看到它存储了传递给aSemaphore + 32
和aSemaphore + 36
的值。我还发现dispatch_semaphore_wait
和dispatch_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/