UIImage imageNamed未正确自动释放

MrH*_*Hen 3 memory iphone objective-c uiimage

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

selectedImage = [UIImage imageNamed:@"icon_72.png"];
[selectedImage release];
Run Code Online (Sandbox Code Playgroud)

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

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

@property (nonatomic, readonly) UIImage *selectedImage;
@synthesize delegate, selectedImage, spacerBottom, currentIndex;
Run Code Online (Sandbox Code Playgroud)

其他说明,这确实打破了:

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”.
Run Code Online (Sandbox Code Playgroud)

由于这样的:

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”.
Run Code Online (Sandbox Code Playgroud)

所以了以下内容:

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”.
Run Code Online (Sandbox Code Playgroud)

这样:

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”.
Run Code Online (Sandbox Code Playgroud)

Jas*_*ien 11

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

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

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

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

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

希望这可以解决问题.

  • 您不应该关注保留计数的实际值.您应该关心的是,您从方便方法收到的对象不会被您保留,因此您不应该将其保留.如果您不希望因任何原因缓存图像,则应使用另一种创建它们的方法,例如,-imageWithContentsOfFile:不缓存图像(在该方法的文档中说明).您可以期望从imageWithContentsOfFile:返回的图像对象被自动释放而不是缓存,并且它将在运行循环结束时被释放. (3认同)

dea*_*rne 8

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

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

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

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

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