发送到已释放实例的消息——简短

发布于 2024-12-07 05:14:17 字数 1999 浏览 1 评论 0原文

这必须是非常基本的,但我没有看到问题。每当执行以下代码块时,程序就会崩溃。分析器报告可能的内存泄漏:

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

消息为 -[UIImage release]:消息发送到已释放实例0x1129d920*

实例0x1129d920已缩放图像

我尝试过像这样添加保留和释放,

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];

}

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

This has to be very basic, but I don't see the problem. The program crashes whenever the following code block is executed. Analyzer reports a possible memory leak:

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

The message is -[UIImage release]: message sent to deallocated instance 0x1129d920*

Instance 0x1129d920 is scaledImage

I tried adding retains and releases, like this

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

and still get the error message.

So I tried replacing the assignment with a copy, like this

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

And the problem is gone.

Checking the scaleToFitWithin method, I see it returns an autoreleased object:

- (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];

}

So there is something about memory management that I'm not understanding. What is the problem likely to be?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空城之時有危險 2024-12-14 05:14:17

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

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

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

The problem is most likely that the scaleToFitWithin:interpolationQuality: method is calling autorelease on an object which has already previously been autoreleased. This can occur if you initialise the UIImage using a temporary constructor, like +[UIImage imageWith...], earlier in the same method you call the scaling method from. The reason it works when you use [anImage copy] is because the behaviour of the copy constructor is such that the object returned to you has already had retain called on it (so it has a local retain count of 1 and zero autoreleases).

What happens at the end of the current run loop is: the autorelease pool which is currently in use is drained, and as a part of that two release messages will be sent to the UIImage. When the first one is sent, the application then runs off and calls dealloc on the image, because the retainCount has decreased to zero. When the second one is sent, the application throws an exception because a message is being sent to an object which was previously deallocated.

Try removing the autorelease message from the scaleToFitWithin:interpolationQuality: method. Even if your resizedImage:interpolationQuality: method IS returning a new object, you should only be calling autorelease in that method rather than the scaling method.

花心好男孩 2024-12-14 05:14:17

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

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

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

It seems that the method resizedImage:interpolationQuality: itself returns an autoreleased object and you are again autoreleasing it in the reutun statement. Just remove the autorelease from the return statement,

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

Then you don't have to retain/release or copy the returned object in if (anImage) {...} block.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文