Сообщение отправлено освобожденному экземпляру - коротко и просто - PullRequest
1 голос
/ 30 сентября 2011

Это должно быть очень просто, но я не вижу проблемы.Программа аварийно завершает работу при выполнении следующего блока кода.Анализатор сообщает о возможной утечке памяти:

if (anImage) {
    eventImageView.frame = defaultEventImageFrame;
    UIImage *scaledImage = [anImage scaleToFitWithin:defaultEventImageFrame.size interpolationQuality:kCGInterpolationHigh];
    eventImageView.backgroundColor = [UIColor colorWithPatternImage:scaledImage];                
}

Сообщение - [UIImage release]: сообщение отправлено освобожденному экземпляру 0x1129d920 *

Экземпляр 0x1129d920 является scaledImage

Я попытался добавить сохранения и выпуски, как это

if (anImage) {
    eventImageView.frame = defaultEventImageFrame;
    UIImage *scaledImage = [[anImage scaleToFitWithin:defaultEventImageFrame.size interpolationQuality:kCGInterpolationHigh] retain];
    eventImageView.backgroundColor = [UIColor colorWithPatternImage:scaledImage];                
    [scaledImage release];        
}

, и все еще получаю сообщение об ошибке.

Поэтому я попытался заменить назначение на копиювот так

if (anImage) {
    eventImageView.frame = defaultEventImageFrame;
    UIImage *scaledImage = [anImage copy];
    eventImageView.backgroundColor = [UIColor colorWithPatternImage:scaledImage];                
}

И проблема исчезла.

Проверяя метод scaleToFitWithin, я вижу, что он возвращает автоматически выпущенный объект:

- (UIImage *) scaleToFitWithin:(CGSize) newSize
          interpolationQuality:(CGInterpolationQuality)quality{

    CGSize originalImageSize = self.size;
    CGSize newImageSize;
    if (originalImageSize.width <= originalImageSize.height) {
        newImageSize.width = self.size.width * newSize.width  / self.size.width;
        newImageSize.height = self.size.height * newSize.width  / self.size.width;
    }
    else {
        newImageSize.width = self.size.width * newSize.height  / self.size.height;
        newImageSize.height = self.size.height * newSize.height  / self.size.height;        
    }
    return [[[self normalize] resizedImage:newImageSize interpolationQuality:kCGInterpolationHigh] autorelease];

}

Итак, есть что-топро управление памятью, которое я не понимаю.Какая проблема может быть?

Ответы [ 2 ]

1 голос
/ 30 сентября 2011

Кажется, что метод resizedImage:interpolationQuality: сам возвращает объект autoreleased, и вы снова автоматически высвобождаете его в операторе reutun .Просто удалите autorelease из оператора return ,

return [[self normalize] resizedImage:newImageSize 
                 interpolationQuality:kCGInterpolationHigh];

Тогда вам не нужно сохранять / выпускать или копировать возвращенноеобъект в if (anImage) {...} блоке.

1 голос
/ 30 сентября 2011

Скорее всего, проблема в том, что метод scaleToFitWithin:interpolationQuality: вызывает autorelease для объекта, который ранее уже был autorelease d. Это может произойти, если вы инициализируете UIImage с помощью временного конструктора, например +[UIImage imageWith...], ранее в том же методе, из которого вызываете метод масштабирования. Причина, по которой он работает, когда вы используете [anImage copy], заключается в том, что поведение конструктора copy таково, что возвращаемому вам объекту уже был вызван retain (поэтому он имеет локальный счетчик хранения 1 и ноль *). 1009 * с).

В конце текущего цикла выполнения происходит следующее: пул автоматического выпуска, который используется в данный момент, сливается, и как часть этих двух release сообщений будет отправлено на UIImage. Когда отправляется первый, приложение запускается и вызывает dealloc на изображении, потому что retainCount уменьшилось до нуля. Когда отправляется второй, приложение выдает исключение, потому что сообщение отправляется объекту, который был ранее освобожден.

Попробуйте удалить сообщение autorelease из метода scaleToFitWithin:interpolationQuality:. Даже если ваш resizedImage:interpolationQuality: метод возвращает новый объект, вы должны вызывать autorelease только в этом методе, а не в методе масштабирования.

...