UIImage imageNamed未正确自动释放

时间:2010-05-28 15:15:50

标签: iphone objective-c memory uiimage

出于某种原因,以下代码中的保留/释放行为让我感到困惑。

selectedImage = [UIImage imageNamed:@"icon_72.png"];
[selectedImage release];

应该中断但。为什么?我认为imageNamed自我释放,这意味着这里的释放是多余的,并且应该在自动释放发生时中断。

以下是与.h和.m文件中的selectedImage相关的代码段:

@property (nonatomic, readonly) UIImage *selectedImage;
@synthesize delegate, selectedImage, spacerBottom, currentIndex;

其他说明,确实打破:

selectedImage = [UIImage imageNamed:@"icon_72.png"];
[selectedImage release];
[selectedImage release];
//objc[55541]: FREED(id): message release sent to freed object=0x59245b0
//Program received signal:  “EXC_BAD_INSTRUCTION”.

确实

selectedImage = [UIImage imageNamed:@"icon_72.png"];
[selectedImage release];
[selectedImage autorelease];
//objc[55403]: FREED(id): message autorelease sent to freed object=0x59b54c0
//Program received signal:  “EXC_BAD_INSTRUCTION”.

所以确实以下内容:

selectedImage = [UIImage imageNamed:@"icon_72.png"];
[selectedImage autorelease];
[selectedImage release];
//objc[55264]: FREED(id): message release sent to freed object=0x592c9a0
//Program received signal:  “EXC_BAD_INSTRUCTION”.

所以确实这个:

selectedImage = [UIImage imageNamed:@"icon_72.png"];
[selectedImage autorelease];
[selectedImage autorelease];
//objc[55635]: FREED(id): message release sent to freed object=0x5b305d0
//Program received signal:  “EXC_BAD_INSTRUCTION”.

4 个答案:

答案 0 :(得分:11)

-imageNamed:返回一个自动释放的图像,正如deanWombourne所说,将在未来的某个时间自动释放(确切的时间未定义)。

它可能习惯于自动释放的原因是-imageNamed还会缓存它返回的图像。缓存保留图像。

基本上,保留周期是这样的:

  • -imageNamed:called,
    • 系统分配和初始化图像 - 保留计数= 1;
    • 系统缓存图像 - 保留计数= 2;
    • 系统自动释放图像并返回给您 - 保留计数= 1; (理论上,图像的保留计数仍为2,因为自动释放池尚未释放它。)
  • 你在图像上调用release - retain count应该是0并且对象应该被释放。
  • 在将来的某个时刻(在运行循环结束时),自动释放池应该释放图像,并且因为你已经过度释放它而崩溃。

如果您不释放它,缓存将继续保留图像,直到它释放它,例如发生内存警告时。因此,当您使用imageNamed获取图像时,它将不会被释放,直到清除缓存。

希望这可以解决问题。

答案 1 :(得分:8)

奇怪而且奇怪,是的。但并非完全无法解释。这就是我认为正在发生的事情。

你是对的; imageNamed:返回一个自动释放的对象。这意味着它将在未来的某个时间发布,所以你马上调用它不会导致错误 - 释放不是通灵,它不知道自动释放池也会释放它! / p>

如果您让代码运行,自动释放池最终将尝试再次释放它,然后您将收到您期望的错误。

你实际上回答了我们自己的问题 - 你说'应该在自动释放时发生断裂'这是绝对正确的,当自动释放发生时,它会破坏:)

其他示例会中断,因为您通过直接调用它们或执行足够的东西来触发autorelase池运行并为您调用release来强制释放。 (您无法预测何时自动释放池将运行,您可以知道在运行循环的某个时刻,自动释放的东西可能会被释放。)

答案 2 :(得分:0)

你说“这应该打破”

selectedImage = [UIImage imageNamed:@"icon_72.png"];
[selectedImage release];

你错了。

如果UIImage是你和我从Cocoa书中写下并学会写的那种类的实例,它可能会破坏,但是我们没有写它,所以我们不应该猜测它的实现。

UIImage如何工作是一个实现细节,而不是您的关注。所有你知道的是,如果你遵守规则,你应该能够使它工作,我相信这些规则现在被称为NARC,而你在这里没有做过。如果你不正确地使用它们,对象肯定会被“破坏”。当你通过它们时,你不能指望被解除分配的对象 - 这不是内存管理合同的一部分。

并非所有Apple的对象都像文本书类/实例一样工作 - 实际上,对象可能会被缓存,重用,回收甚至根本不是对象。

不要担心,遵守规则。

答案 3 :(得分:0)

当我创建此类别时:

@implementation UIImage (ReleaseChecks)

+ (id)allocWithZone:(NSZone *)zone
{
    id o = [super allocWithZone:(NSZone *)zone];
    NSLog(@"Image post-ALLOC: 0x%x",
                (unsigned int)o );
    return o;
}

- (id)autorelease
{
    NSLog(@"Image pre-AUTORELEASE: 0x%x; Retain Count %u",
                (unsigned int)self,
                (unsigned int)[self retainCount]
                );
    return [super autorelease];
}

- (void)release
{
    NSLog(@"Image pre-RELEASE: 0x%x\n; Retain Count %u",
                (unsigned int)self,
                (unsigned int)[self retainCount]
                );
    [super release];
}

- (void)dealloc {
    NSLog(@"Image pre-DEALLOC: 0x%x\n; Retain Count %u",
                (unsigned int)self,
                (unsigned int)[self retainCount]
                );
    [super dealloc];
}

当使用+ imageNamed:分配时,似乎没有调用-autorelease。

然而,当我使用+ imageNamed创建了一大堆这些:然后获得内存警告时,我可以看到它们全部释放和dealloc。这是在iPhone模拟器4.0上测试的。