views:

95

answers:

3

I have the following situation, which seems to cause my iPad application to leak memory.

I have a class with a string property...

@property(nonatomic,retain) NSString * synopsis;

I set the string property from some HTTP response, either from JSON or XML response.

At that point the retain count of the synopsis object is 1.

But I have this situation:

I save the synopsis to a local sqlite database, and then I want to release it from memory, but I have the situation where strangely, calling [synopsis release] from within my object does not decrement the retain count to 0.

(void) save
{
  NSLog(@"synopsis before save retainCount=%d",[synopsis retainCount]);
  [self saveToDb:synopsis withKey:@"synopsis"];
  NSLog(@"synopsis after save retainCount=%d",[synopsis retainCount]);
  [synopsis release];
  NSLog(@"synopsis after release retainCount=%d",[synopsis retainCount]);
  synopsis=nil;
}

In the console I get:

synopsis before save retainCount=1

synopsis after save retainCount=1

synopsis after release retainCount=1

How can this be possible? I get the same result running in simulator or on the device.

}

+9  A: 

DON'T RELY ON RETAINCOUNT!

To humans, it's not an accurate measure of object ownership. You don't know what's calling retain and release behind the scenes in a framework.

Memory management in Cocoa is simple:

  1. If you alloc/init or copy an object, make sure you call release on it at some point.
  2. If you want to keep an object around, call retain -- but make sure to call release at some point, too.
mipadi
Thanks. I understand, but I'm trying to find out why my app runs out of memory... I assume my synopsis property is not getting freed for some reason. Instruments is not helping at this point (no leaks found, allocations look ok, etc.)
Robert Stewart
@mipadi: Please make your first sentence bold. And increase the font size if you can. retainCount is absolutely useless as a debugging tool as this example shows.
JeremyP
I agree on your objections against `retainCount`. Still, I think in this case, it's good to understand what's going on and **why** retainCount always returns one.
Nikolai Ruhe
+1 please file a dupe of this bug: http://openradar.appspot.com/radar?id=435406
Dave DeLong
@Dave DeLong: I wonder if removing `retainCount` would be a good idea. It could possibly break old code, but I doubt any serious code uses `retainCount` anyway (it's practically useless).
mipadi
+1  A: 

Your third NSLog probably calls retainCount on a deallocated object.

The fact, that you see a value of 1 can have three reasons:

  1. There's some other object at the same address now, that has a retain count of one.
  2. (more likely) The deallocated object is still there. It responds to the message by returning the retain count, which would be one because it never was decremented to zero (no need to do that ever, since a deallocated object does not need a valid retain count).
  3. The object is still there and has some custom memory management, preventing retainCount from being decremented.

Edit:

To check deallocation of objects (if you want to be sure), you could always override dealloc and set a breakpoint or put a log message there.

Nikolai Ruhe
Yeah that makes sense. Thanks.
Robert Stewart
+1  A: 

This might help. From the docs about retainCount:

Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

To understand the fundamental rules of memory management that you must abide by, read “Memory Management Rules”. To diagnose memory management problems, use a suitable tool:

• The LLVM/Clang Static analyzer can typically find memory management problems even before you run your program.

• The Object Alloc instrument in the Instruments application (see Instruments User Guide) can track object allocation and destruction.

• Shark (see Shark User Guide) also profiles memory allocations (amongst numerous other aspects of your program).

Jonah