释放不释放对象

Posted

技术标签:

【中文标题】释放不释放对象【英文标题】:Release doesn't dealloc object 【发布时间】:2013-06-19 11:20:04 【问题描述】:

我有一个问题现在可能没有任何实际用处,因为 ARC 受到高度鼓励,但我正在研究内存管理,有些东西我不太明白。

我有这个方法

+(NSNumber *)releaseTooEarly

    NSNumber *createdNumber = [[NSNumber alloc] initWithInteger:5];

    NSLog(@"retain count before release: %d", createdNumber.retainCount); //Prints 2

    [createdNumber release];

    NSLog(@"%@", createdNumber); //Prints 5

    return createdNumber;

    如果对象刚刚创建,保留计数应该是 1 而不是 2? 我知道在这种情况下我应该使用自动释放,这样我就可以返回值,并且调用者可以在它被释放之前使用它。我虽然如果我使用保留它会立即释放对象,但下一个 NSLog 显示它仍然存在,并且值成功返回。

我想知道我是否在一个不允许我在函数中释放对象的自动释放池中。

我知道我应该使用 ARC,但我只是想了解这个结果的原因。

【问题讨论】:

据我所知,当retain count达到0时,对象只是被标记为删除,并没有真正被删除。我不是 MRC 的专家,但可能是错误的。 @Fonix:当保留计数达到 0 时,立即释放对象 。但这并不一定意味着内存无效。 - 但在这种情况下,保留计数未达到 0,如我的回答中所述。 【参考方案1】:

您永远不应依赖保留计数的特定值(请参阅http://whentouseretaincount.com)。

在这种特殊情况下(可以在http://www.opensource.apple.com/source/CF/CF-476.19/CFNumber.c 中看到),NSNumber 缓存创建的对象之间的整数值 (-1) 和 12,这样调用

[[NSNumber alloc] initWithInteger:5];

重复将始终返回相同的实例。缓存保存一个对对象的附加引用 这是retainCount == 2的原因,也解释了为什么对象不是 如果你释放它实际上会被摧毁。

但这只是实现细节!!。如上所述,您不应该使用保留计数。即使一个对象被释放,也不一定意味着该对象的内存无效,因此访问该对象可能会显示结果。

有关规则,请参阅“高级内存管理编程指南”中的"Basic Memory Management Rules":

您最终必须拥有releaseautorelease 对象。 您拥有使用名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法创建的对象 如果您使用 retain 取得所有权,则您拥有一个对象。

你的方法的正确版本是

+ (NSNumber *)releaseCorrectly

    NSNumber *createdNumber = [[[NSNumber alloc] initWithInteger:5] autorelease];
    return createdNumber;

autorelease 平衡了alloc,但确保对象仍然有效 返回调用方法时。会在当前自动释放时释放 池被破坏,例如当程序控制返回到主事件循环时。

【讨论】:

谢谢!你提供给我的链接真的很有用。

以上是关于释放不释放对象的主要内容,如果未能解决你的问题,请参考以下文章

已释放对象的校验和不正确 - 对象在被释放后可能已被修改。我该如何解决?

@property(保留)是不是自动释放或释放对象?

如何找到带有自动释放消息的对象?

移除对象时内存未释放 - 不清楚在 ARC 中释放的正确方法

using不是自动释放连接对象吗?

从 NSArray 返回的自动释放对象?