为啥我在使用 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 等),看看它是否会在某一时刻起作用。 对不起,那是不久前的事了。我将NSTextFields 存储在一个数组中并访问了它们。感谢您的帮助:)

以上是关于为啥我在使用 GCD 时收到错误 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)的主要内容,如果未能解决你的问题,请参考以下文章

为啥我会收到“错误:序列化从 getStaticProps 返回的 ___ 时出错”?

我在解析 JSON 时遇到错误。为啥我会收到这个错误?

为啥我在尝试设置 PayPal 付款时在生产中不断收到 INVALID_RESOURCE_ID 错误?

为啥我在尝试使用 fetch 连接 Api 时收到“错误请求”错误 400?

为啥我在使用 isNull 时收到此错误消息

为啥我在运行 Locust 时收到 403 错误?