Iphone UIImage ImageName未正确自动释放

Iphone UIImage ImageName未正确自动释放,iphone,objective-c,memory,uiimage,Iphone,Objective C,Memory,Uiimage,出于某种原因,下面代码中的保留/释放行为让我完全困惑不解 selectedImage = [UIImage imageNamed:@"icon_72.png"]; [selectedImage release]; 这应该会断开,但不会断开。为什么?我认为imageNamed自动释放本身意味着这里的释放是多余的,当自动释放发生时应该中断 以下是与.h和.m文件中selectedImage相关的代码片段: @property (nonatomic, readonly) UIImage *selec

出于某种原因,下面代码中的保留/释放行为让我完全困惑不解

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 autorelease];
//objc[55635]: FREED(id): message release sent to freed object=0x5b305d0
//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 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 autorelease];
//objc[55635]: FREED(id): message release sent to freed object=0x5b305d0
//Program received signal:  “EXC_BAD_INSTRUCTION”.

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

你是对的<代码>图像名:返回自动删除的对象。这意味着它将在将来某个时候被释放,所以你直接调用release不会导致错误-释放不是通灵的,它不知道自动释放池也会释放它

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

你实际上已经回答了我们自己的问题——你说“当自动释放发生时应该中断”,这是绝对正确的,当自动释放发生时,它将中断:)


其他示例之所以中断,是因为您通过直接调用发布或执行足够的操作来强制发布,从而触发自动弹性池运行并为您调用发布。(您无法预测自动释放池何时运行,您只需知道在运行循环的某个时刻,自动释放的内容可能会被释放。)

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

它没有在您可能已经习惯的时候自动释放的原因是-imageNamed还缓存它返回的图像。缓存正在保留图像

所以本质上,保留周期是这样的:

  • -ImageName:called,
    • 系统allocs和init的一个映像--retaincount=1
    • 系统缓存图像——保留计数=2
    • 系统自动释放图像并返回给您--retain count=1;(理论上,图像的保留计数仍然为2,因为自动释放池尚未释放它)
  • 对映像调用release--retain count应为0,并且对象应被释放
  • 在将来的某个时候(在运行循环结束时),自动发布池应该会发布映像,并且会因为您过度发布而崩溃
如果不释放该图像,缓存将继续保留该图像,直到它释放该图像为止,例如,当出现内存警告时。因此,当您使用ImageName获取图像时,它不会被释放,直到清除缓存

希望这能把事情弄清楚。

你说“这应该打破了”

你错了

如果UIImage是您和我从Cocoa书籍中编写和学习编写的类的实例,它可能会崩溃,但我们没有编写它,所以我们不应该猜测它的实现

UIImage的工作原理是一个实现细节,而不是您所关心的。你所知道的是,如果你遵守这些规则,你应该能够期待它起作用,我相信这些规则现在被称为NARC,而你在这里没有做到。如果使用不当,任何地方都不能保证对象会“损坏”。当您处理完对象时,您不能指望对象被解除分配—这不是内存管理契约的一部分

并非所有苹果的对象都像教科书类/实例那样工作——事实上,对象可能被缓存、重用、回收,甚至根本不是对象


不用担心,请遵循规则。

当我创建此类别时:

@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];
}
与+ImageName:一起分配时,似乎未调用-autorelease


然而,当我用+imageNamed:创建了一整组时,然后得到一个内存警告,我可以看到它们都是release和dealloc。这是在iPhone Simulator 4.0上测试的。

就像海报上说的,你实际上是在过度释放selectedImage,每当你调用一个类方法,它都会返回一个自动释放的对象。我的印象是,一旦程序返回到事件循环,自动释放池就会耗尽。这不对吗?我可以让程序打开一段时间,永远不会看到它崩溃。是的,自动释放池将永远不会让东西“长时间”存在。诚然,不能保证它什么时候会被耗尽,但这并不是你必须让你的程序运行一段时间才能发现的。Jasarien的回答正确地解释了在这种特殊情况下会发生什么。啊,缓存位是一个很好的提示。是否有地方可以让我了解缓存如何影响保留计数?即使我的程序不再保留UIImage对象,缓存是否可能保留该对象?您不应该关心保留计数的实际值。您应该关心的是,您从便利方法接收到的对象不是由您保留的,因此您不应该释放它。如果出于任何原因不希望缓存图像,则应使用另一种创建图像的方法,例如,-imageWithContentsOfFile:不缓存图像(该方法的文档中已说明)。您可以预期从imageWithContentsOfFile:返回的图像对象将自动删除而不是缓存,并将在运行循环结束时解除分配。“它将在运行循环结束时解除分配。”-前提是您根本不保留它(即,将其设置为imageView的图像,将其添加到数组中,等等)1.我真的不关心重新入帐的事。我只是觉得这种行为很奇怪。我将把实现切换到imageWithContentsOfFile并查看