发布不会释放对象

时间:2013-06-19 11:20:04

标签: objective-c memory-management nsautoreleasepool

我有一个问题可能现在没有任何实际用途,因为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. 如果刚刚创建了对象,那么保留计数应该是1还是2?
  2. 我知道在这种情况下我应该使用autorelease,所以我可以返回值,并且调用者可以在释放之前使用它。我虽然如果我使用retain而不是它会立即释放该对象,但是下一个NSLog显示它仍然退出,并且该值已成功返回。
  3. 我想知道我是否在自动释放池中,不允许我在函数中释放对象。

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

1 个答案:

答案 0 :(得分:2)

您永远不应该依赖保留计数的特定值(请参阅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,但确保对象仍然有效 当返回调用方法时。它将在当前自动释放时释放 池被破坏,例如程序控制返回主事件循环时。