出于某种原因,以下代码中的保留/释放行为让我感到困惑。
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”.
答案 0 :(得分:11)
-imageNamed:返回一个自动释放的图像,正如deanWombourne所说,将在未来的某个时间自动释放(确切的时间未定义)。
它可能习惯于自动释放的原因是-imageNamed还会缓存它返回的图像。缓存保留图像。
基本上,保留周期是这样的:
如果您不释放它,缓存将继续保留图像,直到它释放它,例如发生内存警告时。因此,当您使用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上测试的。