zyxel
zyxel

Reputation: 1094

Why I get error EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) when I use GCD

Could somebody, please, explain me why I get error EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) in dispatch_semaphore_wait in the following code:

-(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);
  });
}

I found similar question Why does this code cause "EXC_BAD_INSTRUCTION"?, but in my case I am using ARC and I do not write explicitly nowhere dispatch_release(sem);

Upvotes: 1

Views: 11828

Answers (3)

Ken Thomases
Ken Thomases

Reputation: 90571

You are allowing simultaneous access to the array self.myarray without sufficient protection. You modify the array with -addObject: and -removeObjectAtIndex: on the serial queue self.queue but you read from it using -objectAtIndex: without any protection. That means you may be reading from it at the same time you're writing to it, which is not safe. You need to also put the -objectAtIndex: call on the serial queue.

Also, you are using barrier functions with a serial queue, which doesn't make any sense.

-(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);
  });
}

Upvotes: 1

kalmiya
kalmiya

Reputation: 3116

This kind of crash will happen when you are running a (vector)extension which is not supported on your CPU.

For example, in xcode 5 under "project-settings / build-settings / Code Generation, set the "Enable Additional Vector extensions" to "AVX2". Build your executable.

Now run it on an:

  • Intel Core i5: it's going to crash (wherever the compiler decided to use avx2) with 'exc_i386_invop subcode=0x0'.
  • Intel Core i7: it will work.

Upvotes: 0

ipmcc
ipmcc

Reputation: 29906

The sem you created in your initialize method is locally scoped to that method. It needs to be accessible to the other methods. If you have an iVar named sem that you're attempting to assign, you're shadowing it by declaring a local variable in initialize. (Same thing with queue, by the way.)

Also, you appear to have a typo here, in that you call dispatch_semaphore_wait(sen, DISPATCH_TIME_FOREVER); (i.e. se n vs se m)

Upvotes: 2

Related Questions