我有一个带有以下初始化方法的类:

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
        StateStack* s = [[StateStack alloc] init];
        state = s;
        [s push:NONE]; //<--EXC_BAD_ACCESS on load here
        [s release];
    }

    return self;
}


StateStack具有以下初始化代码:

- (id)init {
    self = [super init];
    if (self) {
        NSMutableArray* s = [[NSMutableArray alloc] init];
        stack = s;
        [s release];
        NSLog(@"%d",[stack retainCount]);
    }
    return self;
}


奇怪的是,如果我删除NSLog行,则EXC_BAD_ACCESS移至StateStack的dealloc方法:

- (void)dealloc {
    [stack release]; //<--EXC_BAD_ACCESS
    [super dealloc];
}


到处搜索似乎表明EXC_BAD_ACCESS是由过度释放引起的,但是我看不到我是如何过度释放的。有人知道原因是什么吗?

最佳答案

init函数中:

    StateStack* s = [[StateStack alloc] init];
    state = s;
    [s push:NONE]; //<--EXC_BAD_ACCESS on load here
    [s release];


您正在分配StateStack的实例;它的保留计数为1。然后,在调用release的函数结束时,保留计数变为0,并且对象已准备好释放。因此,当以后执行dealloc时,会将state ivar发送给另一个release,这将导致错误的访问。您不需要释放s,因为您希望保留该状态。在另一个init方法中会发生相同的错误模式。

这是正确的:

- (id)init
{
  self = [super init];
  if (self) {
    // Initialization code here.
    StateStack* s = [[StateStack alloc] init];
    state = s;
    [s push:NONE]; //<--EXC_BAD_ACCESS on load here
  }

  return self;
}

- (id)init {
   self = [super init];
   if (self) {
     NSMutableArray* s = [[NSMutableArray alloc] init];
     stack = s;
   }
   return self;
 }


注意:我不想引起误解。使用保留计数检查正确的内存分配是没有用的。这是真的。无论如何,根据保留计数进行推理有助于了解分配/释放/自动释放对象时发生的情况。这是基本机制,但是要跟踪其使用情况以检查内存管理的正确性太困难了。

关于objective-c - 寻找EXC_BAD_ACCESS的原因,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6823053/

10-11 04:04