Поиск причины EXC_BAD_ACCESS - PullRequest
2 голосов
/ 26 июля 2011

У меня есть класс со следующим методом инициализации:

- (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переходит к методу dealloc StateStack:

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

Похоже, поиск вокруг предполагает, что EXC_BAD_ACCESS вызван чрезмерным выпуском, но я не вижу, как я перевыпустил что-либо.Кто-нибудь знает, в чем может быть причина?

Ответы [ 3 ]

3 голосов
/ 26 июля 2011

state = s не копирует объект NSMutableArray, он просто копирует указатель на него. Поэтому, когда вы вызываете [s release], объект, на который ссылаются s и состояние, освобождается. Вы получите EXC_BAD_ACCESS всякий раз, когда будете использовать любой из этих пунктов.

Кроме того, не используйте [object retainCount] для устранения проблем с управлением памятью. Это ложь. Google NSZombies.

3 голосов
/ 26 июля 2011

В вашей 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;
 }

NB. Я не хочу создавать недоразумений. Использование retain count для проверки правильного распределения памяти бесполезно. Это правда. В любом случае, рассуждения с точки зрения количества записей помогают понять, что происходит, когда вы выделяете / отпускаете / автоматически выпускаете объект. Это основной механизм, но слишком сложно отследить его использование, чтобы проверить правильность управления памятью.

1 голос
/ 26 июля 2011
- (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;

}

...