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,并且对象应被释放
- 在将来的某个时候(在运行循环结束时),自动发布池应该会发布映像,并且会因为您过度发布而崩溃
不用担心,请遵循规则。当我创建此类别时:
@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并查看