为啥我在使用 GCD 时收到错误 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Posted
技术标签:
【中文标题】为啥我在使用 GCD 时收到错误 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)【英文标题】:Why I get error EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) when I use GCD为什么我在使用 GCD 时收到错误 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) 【发布时间】:2013-08-01 13:44:31 【问题描述】:请有人解释一下为什么我在以下代码中的 dispatch_semaphore_wait 中收到错误 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0):
-(void) initialize
dispatch_queue_t queue = dispatch_queue_create("My queue", NULL);
dispatch_semaphore_t sem = dispatch_semaphore_create(1);
self.queue = queue;
self.sem = sem;
self.myarray = [[NSMutableArray alloc]init];
[self.myarray addObject: [[MyObject alloc] init]];
-(MyObject *) method1
//do something
dispatch_semaphore_wait(self.sem, DISPATCH_TIME_FOREVER);
MyObject *obj = [self.myarray objectAtIndex:0];
dispatch_barrier_sync(self.queue, ^
[self.myarray removeObjectAtIndex:0];
);
return obj;
-(void) method2:(MyObject *)object
//do something
dispatch_barrier_async(self.queue, ^
[self.myarray addObject:object];
dispatch_semaphore_signal(self.sem);
);
我发现了类似的问题Why does this code cause "EXC_BAD_INSTRUCTION"?,但在我的情况下,我使用的是 ARC,并且我没有明确写出 nowhere dispatch_release(sem);
【问题讨论】:
“队列”是如何定义的?显然 -initialize 中的那个不是同一个。 同样,我忘了添加将局部变量分配给实例变量的代码 所以...呃...您修复了代码后还有问题吗?因为如果这修复了您的代码,那么您应该接受答案,而不是编辑问题使其毫无意义。 我没有更改代码,我只编辑了我在此处发布的文本中的一些拼写错误和不准确之处。现在这里的代码是我在程序中的代码。所以答案是否定的,它没有解决问题。 @nru 你确定实例方法initialize
在你发送method1
和方法method2
之前已经被调用了吗?在使用之前检查信号量和队列 ivar 是否不为零,例如assert(self.sem)
。此外,您的代码没有意义。您对信号量的使用也不正确,因为即使数组为空,它也不会阻止访问数组,因此您会遇到异常。
【参考方案1】:
您在initialize
方法中创建的sem
在本地范围为该方法。它需要可供其他方法访问。如果您尝试分配一个名为sem
的iVar,则通过在initialize
中声明一个局部变量来隐藏它。 (顺便说一下,queue
也是如此。)
此外,您在这里似乎有一个错字,因为您调用 dispatch_semaphore_wait(sen, DISPATCH_TIME_FOREVER);
(即 se n 与 se m)
【讨论】:
【参考方案2】:您允许在没有足够保护的情况下同时访问阵列self.myarray
。您在串行队列self.queue
上使用-addObject:
和-removeObjectAtIndex:
修改阵列,但您使用-objectAtIndex:
从它读取而没有任何保护。这意味着您可能在写入的同时正在读取它,这是不安全的。您还需要将-objectAtIndex:
调用放在串行队列中。
此外,您正在使用带有串行队列的屏障函数,这没有任何意义。
-(MyObject *) method1
//do something
dispatch_semaphore_wait(self.sem, DISPATCH_TIME_FOREVER);
__block MyObject *obj;
dispatch_sync(self.queue, ^
obj = [self.myarray objectAtIndex:0];
[self.myarray removeObjectAtIndex:0];
);
return obj;
-(void) method2:(MyObject *)object
//do something
dispatch_async(self.queue, ^
[self.myarray addObject:object];
dispatch_semaphore_signal(self.sem);
);
【讨论】:
【参考方案3】:当您运行 CPU 不支持的(向量)扩展时,会发生这种崩溃。
例如,在 xcode 5 中的“project-settings / build-settings / Code Generation 下,设置 “启用附加矢量扩展”到“AVX2”。构建您的可执行文件。
现在运行它:
英特尔酷睿 i5:它将崩溃(无论编译器决定使用 avx2),并出现“exc_i386_invop subcode=0x0”。 英特尔酷睿 i7:它会工作。【讨论】:
这对我不起作用。当我尝试在表委托中的tableView:viewForTableColumn:row:
中调用 tableColumn?.identifier
时,我收到此错误
尝试禁用矢量扩展(avx2、sse 等),看看它是否会在某一时刻起作用。
对不起,那是不久前的事了。我将NSTextField
s 存储在一个数组中并访问了它们。感谢您的帮助:)以上是关于为啥我在使用 GCD 时收到错误 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)的主要内容,如果未能解决你的问题,请参考以下文章
为啥我会收到“错误:序列化从 getStaticProps 返回的 ___ 时出错”?
为啥我在尝试设置 PayPal 付款时在生产中不断收到 INVALID_RESOURCE_ID 错误?