为什么此代码会导致“EXC_BAD_INSTRUCTION”?
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"); }
所以,是的,你去了,这就是崩溃的原因!
更简洁的答案:您正在使用错误的值创建信号量,它应该为零。 使用值1创建它意味着您稍后释放仍然“正在使用”的信号量,并且GCD故意生成非法指令,以帮助您调试您拥有更多服务员信号量的事实。
你可以创建一个零值的信号量,但我相信它只会毫无用处。 我在一个类中有一个信号量字段,导致它在去初始化时崩溃。 这就是我修复它的方法(Swift代码):
deinit { while (dispatch_semaphore_signal(semaphore) != 0) {} }
一个相当尴尬的补丁,但它的工作原理!
- 从URL读取JSON并添加MKAnnotations
- UITabBarController应用程序和pushViewController失败
- iPhone的iOS如何从相机胶卷图像提取照片元数据和地理标签信息?
- 什么是iPhone 6和6 Plus的平台string?
- 如何从UIGestureRecognizer获取UITouch位置
- presentViewController不支持iOS 6中的方向
- 通过RestKit将JSON的本地NSString反序列化为对象(无networking下载)
- 在Swift中逐像素地应用视觉效果
- 即使configuration正确,URLForUbiquityContainerIdentifier也会返回nil