Question

I have a question that may not be of any practical use right now since ARC is highly encourage, but I'm studying memory management and there's something I didn't quite understand.

I have this method

+(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. If the object was just created, should the retain count be 1 instead of 2?
  2. I understand that in this kind of situations I should use autorelease so I can return the value, and the caller can make use of it before it is deallocated. I though that if I use retain instead it would immediately deallocate the object, but the next NSLog shows that it still exits, and the value is successfully returned.

I'm wondering if I'm inside an autorelease pool that is not allowing me to deallocate the object within the function.

I know I should be using ARC but I just want to understand the reason of this results.

Was it helpful?

Solution

You should never rely on a particular value of the retain count (see http://whentouseretaincount.com).

In this particular case (as can be seen in http://www.opensource.apple.com/source/CF/CF-476.19/CFNumber.c), NSNumber caches the created objects for integer values between (-1) and 12, so that calling

[[NSNumber alloc] initWithInteger:5];

repeatedly will always return the same instance. The cache holds one additional reference to the object which is the reason for retainCount == 2, and also explains why the object is not actually destroyed if you release it.

But this are only implementation details!!. As said above, you should not use the retain count. And even if an object is deallocated that not necessary mean that the memory of the object is invalidated, so accessing the object might show a result.

See "Basic Memory Management Rules" in the "Advanced Memory Management Programming Guide" about the rules:

  • You must eventually release or autorelease objects that you own.
  • You own objects that you created using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”
  • You own an object if you take the ownership using retain.

The correct version of your method would be

+ (NSNumber *)releaseCorrectly
{
    NSNumber *createdNumber = [[[NSNumber alloc] initWithInteger:5] autorelease];
    return createdNumber;
}

The autorelease balances the alloc, but ensures that the object is still valid when returning to the calling method. It will be released when the current autorelease pool is destroyed, e.g. when program control returns to the main event loop.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top