Dealloc называют дважды? - PullRequest
       1

Dealloc называют дважды?

2 голосов
/ 26 июня 2011

Resloved!

Благодаря Lone Gunman эта проблема была вызвана недосмотром того, что многие делегаты не установили ноль перед их освобождением.

Это странно ... Я знаком с основами управления памятью, но думаю, что-то необычное в том, что я вижу. Вот небольшой фон ...

У меня есть NavigationController, который обрабатывает переход между следующими ViewControllers:

Домой -> Игры -> Игра

При запуске кода он падает при выходе из Игры. В GameViewController есть метод dealloc, похожий на:

- (void)dealloc 
{
    [board release];
    [opponentsViewController release];
    [instructionsViewController release];
    [imgPicker release];
    [gameView release];
    [super dealloc];
}

Когда контроллер навигации возвращается к списку Игр (из Игры), он выдает EXC_BAD_ACCESS. Поэтому я поднимаю свой верный профилировщик и проверяю наличие зомби. Увы, как я и ожидал, сообщение отправляется освобожденному объекту! Копая глубже, я нахожу, что в истории объекта есть 3 записи:

  1. Доска получает alloc'd (вызывается методом init Game)
  2. Доска высвобождается (вызывается методом dealloc в игре)
  3. Board - Zombie'd (вызывается методом dealloc Game)

Оба вызова 2 и 3 вызываются из UINavigationController setDisappearingViewController.

В моем методе dealloc я устанавливаю точки останова для каждого вызова освобождения, при этом происходит вызов [release release], затем происходит вызов [oppentsViewController release], затем снова вызывается вызов [board release]. Итак, я вижу, что метод dealloc не завершается полностью и вызывает снова.

Что может быть причиной этого?

Редактировать: это Реализация GameViewController

Код из игрового контроллера, который добавляет эту игру:

-(void) gotoGame:(int)tag {

    game = [[GameViewController alloc] init];
    [self.navigationController pushViewController:game animated:YES];
    [game release];

}

Редактировать: это GameViewController Header

Ответы [ 2 ]

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

Я бы попытался установить все делегаты вашего ивара в ноль (РЕДАКТИРОВАТЬ: в dealloc). У меня была похожая проблема с контроллером полученных результатов. Не удалось установить для его делегата значение nil в dealloc, и в стеке данных ядра все еще имел указатель на него, когда контроллер представления был освобожден.

Так вот, моя ставка, установите для делегатов ivar значение nil в dealloc, хотя я не вижу вашего заголовка, чтобы знать, какие протоколы вы соответствуете, чтобы быть уверенным.

РЕДАКТИРОВАТЬ: Объяснение

Установка делегата на самом деле дает объекту, который выполняет делегирование, указатель (я полагаю, что это обычно назначенное свойство).

@property (assign) delegate;

Я буду использовать проблему, которую я имел в качестве примера.

Итак, допустим, у вас есть контроллер представления, у которого есть fetchedResultsController в качестве ивара. При установке делегата FRC:

fetchedResultsController.delegate = self;

и контроллер представления освобождается, любой объект, который использует этот указатель, все еще думает, что он живой. Вы могли бы подумать, что поскольку FRC выпускается и в dealloc, у вас все будет в порядке (поэтому мне потребовалось 4 дня, чтобы понять это :)), но иногда другие части реализации также используют вашего делегата. Итак, исправление:

-(void)dealloc
{
    self.fetchedResultsController.delegate = nil;
    [_fetchedResultsController release];
    [super dealloc];
}

Примечание: как только новые инструменты станут доступны всем, вам больше не придется об этом беспокоиться ^ ^;

0 голосов
/ 26 июня 2011

попробуй

- (void) dealloc {
    if(game != nil){
     //release here
     [game release];
    }
    [super dealloc];
  }

Кстати, кажется, что вы объявили игру в заголовочном файле и сразу после нажатия вы отпускаете ее, а также в методе dealloc вы отпускаете ее. Удалите вызов release из метода dealloc или измените свой метод следующим образом.

-(void) gotoGame:(int)tag {

    GameViewController *game = [[GameViewController alloc] init];
    [self.navigationController pushViewController:game animated:YES];
    [game release];

}

UPDATE

Также вы нигде не используете тег. Почему бы вам не создать свой метод инициализации, как этот

GameViewController *game = [[GameViewController alloc] initWithTag:tag];
[self.navigationController pushViewController:game animated:YES];
[game release];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...