【问题标题】:Finding the cause of EXC_BAD_ACCESS查找 EXC_BAD_ACCESS 的原因
【发布时间】:2011-07-25 22:17:44
【问题描述】:

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

【问题讨论】:

    标签: objective-c exc-bad-access


    【解决方案1】:

    在您的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】:

      state = s 没有复制 NSMutableArray 对象,它只是复制指向它的指针。因此,当您调用 [s release] 时,s 和 state 引用的对象都被释放。从那时起,无论何时使用任何一个,您都会得到一个 EXC_BAD_ACCESS。

      另外,不要使用[object retainCount] 来调试内存管理问题。它在说谎。谷歌 NSZombies。

      【讨论】:

        【解决方案3】:
        - (id)init{
        self = [super init];
        if (self) {
            // Initialization code here.
            state = [[StateStack alloc] init];
            [state push:NONE];
        }
        return self;
        }
        

        状态栈

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

        }

        【讨论】:

          猜你喜欢
          • 2011-07-25
          • 2011-07-05
          • 2014-04-24
          • 2014-07-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-30
          • 2017-12-26
          相关资源
          最近更新 更多