【问题标题】:Message sent to deallocated instance -- short and simple发送到已释放实例的消息——简短而简单
【发布时间】:2011-09-30 05:22:13
【问题描述】:

这必须非常基本,但我看不出问题所在。每当执行以下代码块时,程序就会崩溃。 Analyzer 报告可能存在内存泄漏:

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

消息是 -[UIImage release]: message sent to deallocated instance 0x1129d920*

Instance 0x1129d920 is 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];

}

所以我不理解关于内存管理的一些内容。可能是什么问题?

【问题讨论】:

    标签: objective-c memory-management memory-leaks


    【解决方案1】:

    问题很可能是scaleToFitWithin:interpolationQuality: 方法在一个之前已经是autoreleased 的对象上调用autorelease。如果您使用临时构造函数(如+[UIImage imageWith...])初始化UIImage,则可能会发生这种情况,之前在您调用缩放方法的同一方法中。当您使用 [anImage copy] 时它起作用的原因是因为 copy 构造函数的行为使得返回给您的对象已经调用了 retain (因此它的本地保留计数为 1 和零 @ 987654329@s)。

    当前运行循环结束时发生的情况是:当前正在使用的自动释放池被耗尽,作为这两条 release 消息的一部分将发送到 UIImage。当第一个被发送时,应用程序然后运行并在图像上调用dealloc,因为retainCount 已经减少到零。当第二个被发送时,应用程序会抛出一个异常,因为一条消息被发送到一个之前被释放的对象。

    尝试从scaleToFitWithin:interpolationQuality: 方法中删除autorelease 消息。即使您的 resizedImage:interpolationQuality: 方法返回一个 new 对象,您也应该只在该方法中调用 autorelease 而不是缩放方法。

    【讨论】:

      【解决方案2】:

      似乎resizedImage:interpolationQuality: 方法本身返回了一个autoreleased 对象,而您又在reutun 语句中自动释放它。只需从 return 语句中删除自动释放,

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

      那么您不必保留/释放复制if (anImage) {...}块中返回的对象。

      【讨论】:

      • 感谢您的建议。当答案很接近时,很难决定谁获得了荣誉。我感谢大卫提供的一点额外解释,但你也说对了。
      猜你喜欢
      • 2011-06-16
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多