Освобождение переменной экземпляра вызывает сбой, но почему? - PullRequest
2 голосов
/ 04 марта 2010

У меня есть переменная экземпляра, определенная и синтезированная как свойство:

@interface CardFrontView : GenericCardView {
    UIImage *_letterImage;
}

@property (nonatomic, retain) UIImage *letterImage;

@end

@implementation CardFrontView
@synthesize letterImage = _letterImage;
...

Я установил свойство letterImage в -init:

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self != nil) {
        NSString *filename = [[NSBundle mainBundle] pathForResource:@"fehu" ofType:@"png"];
        self.letterImage = [UIImage imageWithContentsOfFile:filename];
    }   return self;
}

Затем я выпускаю его в -dealloc, после чего происходит сбой приложения (EXC_BAD_ACCESS):

- (void)dealloc {
    [super dealloc];
    [_letterImage release];
}

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

Ответы [ 3 ]

20 голосов
/ 04 марта 2010

Хорошо ... связываемся воедино из подсказок, оставленных как в вопросе, так и в комментариях.

Во-первых, это:

- (void)dealloc {
    [super dealloc];
    [_letterImage release];
}

Это просто неправильно и может стать источником краха сам по себе. Вы сообщаете экземпляру, которому принадлежит _letterImage, команду dealloc , а затем говорите _letterImage об освобождении. К моменту вызова [_letterImage release] объект, содержащий _letterImage, уже мертв и ушел.

Хотя это может вызвать сбой, вероятно, это не так (но это все равно следует исправить). В комментарии вы говорите:

Я обнаружил, что ошибка исчезла, когда я переехал [super dealloc]. GenericCardView не делает ничего странного в все (только некоторые предварительные настройки, которые является общим для нескольких различных видов Card s). Итак, я понятия не имею, почему это случилось, и это все делает меня скорее неудобно.

Все dealloc методы всегда должны вызывать [super dealloc]; как последнюю строку кода в реализации -dealloc метода . Всегда и без исключения *.

То, что что-то начинает работать, когда вы удаляете вызов на [super dealloc], на 100% гарантирует, что в вашем коде есть ошибка.

В этом случае я не удивлюсь, что ваш класс GenericCardView неправильно управляет переменными экземпляра. Я хотел бы начать с просмотра всех переменных, выпущенных в методе dealloc этого класса, чтобы убедиться, что они правильно управляются в первую очередь (а также проанализировать саму реализацию dealloc).

В любом случае, это очень пахнет проблемой перепроизводства. Верните свой код в состояние, в котором постоянно происходят сбои, затем используйте инструменты обнаружения зомби в Инструменте, чтобы увидеть, обнаруживают ли они сбой и идентифицируют ли объект, который был выпущен повторно. Даже если истинная причина окажется только , которую вы не называли [super dealloc] последним в ваших dealloc методах, подтверждение того, что то есть , должно повысить ваш уровень комфорта .

* На самом деле есть одно исключение; когда вы пишете свой собственный корневой класс. Но это настолько редкое явление, что его нельзя считать. (Счастлив, парень? :)

3 голосов
/ 04 марта 2010

Совершенно независимо от соглашений, которые требуют от вас выпуска или иным образом, реальная проблема с вашим кодом - [super dealloc], за которым следует что-то еще.Как только этот метод вызван, вы больше не можете ничего делать в вашем объекте.

Вместо этого сначала проведите локальную уборку, и только после этого вызовите супер.

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

Алекс

1 голос
/ 04 марта 2010

Вы когда-нибудь обращались к этому в любой другой точке своего кода? Единственное, о чем я могу думать, это то, что он выпускается где-то еще, но не сохраняется первым.

Это также может быть, хотя я в этом сильно сомневаюсь, из-за того, что ваш [super dealloc] звонок является первым, а не последним. Хотя это хорошая практика, чтобы выразить это последним, у меня сложилось впечатление, что это не имеет никакого функционального значения - вы делаете что-то странное в суперклассе, которое может быть причиной этого?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...