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
表示它正在将 32 个字节读入 aSemaphore
指向的结构(它是指向 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/