找到EXC_BAD_ACCESS的原因

时间:2011-07-25 22:17:45

标签: objective-c exc-bad-access

我有一个使用以下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
        [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是由过度释放引起的,但我看不出我是如何过度释放的。有谁知道原因可能是什么?

3 个答案:

答案 0 :(得分:3)

state = s没有复制NSMutableArray对象,它只是将指针复制到它。因此,当您调用[s release]时,s和state引用的对象将被释放。无论何时使用,都可以获得EXC_BAD_ACCESS。

另外,请勿使用[object retainCount]来调试内存管理问题。它的谎言。 Google NSZombies。

答案 1 :(得分:3)

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

注意:我不想产生误解。使用保留计数来检查正确的内存分配是没用的。这是真的。无论如何,在保留计数方面的推理有助于理解在分配/释放/自动释放对象时会发生什么。它是基本机制,但是要检查内存管理的正确性是非常困难的。

答案 2 :(得分:1)

- (id)init{
self = [super init];
if (self) {
    // Initialization code here.
    state = [[StateStack alloc] init];
    [state push:NONE];
}
return self;
}

StateStack

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

}