views:

295

answers:

2

I have been tracking down why NSObject references, while being explicitly release, still show up in ObjectAlloc. In fact, have reduced down NSObject to a basic shell, with a [[myObject alloc]init] immediately followed by a [myObject release], and it does not look like it is being released in ObjectAlloc. This is a big problem with a NavigationController app that pushes/pops multiple view controllers, as the recently popped viewcontrollers aren't being released, because of these 'unreleased' NSObject references. Hmmmmmm.

I could put my code up here, and have a bunch of 'have you's that never get anywhere. Autorelease pools, blah blah.

So, let's look at the Sample 'SeismicXML' sample app from Apple... fire it up in ObjectAlloc/Leaks. Very basic in getEarthquakeData:

XMLReader *streamingParser = [[XMLReader alloc] init];
[streamingParser parseXMLFileAtURL:[NSURL URLWithString:feedURLString] parseError:&parseError];
[streamingParser release];

I see a TON of junk laying around in ObjectAlloc from XMLReader, despite releasing it. I bet if we put a 'refresh' button on this app to call 'getEarthquakeData' again, we would crash the app within 5 refreshes.

Any thoughts?

+2  A: 

I think you are confused about the ObjectAlloc instrument which will show all object allocations for the lifetime of your application. It's main use is to track memory usage over time.

The instrument I think you want is the one that is called Leaks which shows you what memory is being leaked by not having any reference to it. That is pointers to objects not being sent release-dealloc before they are reassigned.

monowerker
+1  A: 

There might be an autorelease pool holding onto the object. If you create many autoreleased objects without cleaning them out of the pool, you'll get leaks until you return to the outer loop with the autorelease pool.

Here's how autorelease pools work: in the main loop, there's an autorelease pool. Everything autoreleased goes there. At the end of every loop iteration, all the objects in the pool get released. If you allocate objects in another loop somewhere, they won't actually get released until you return to the main loop. Unless, of course, you create your own autorelease pool just for the loop.

Another problem could be that your object is never released. If you get an exception between +alloc and -release you'll get a leak. A way to fix this is to use instead:

[[[XMLReader alloc] init] autorelease]

Finally, you could be working with garbage collection here. I don't know enough about the GC system to tell you what behavior you should expect.

Dietrich Epp
Agreed. Read the release docs. This is acceptable behaviour. Have you tried the experiement on the phone as well as the simulator?
Roger Nolan
I have, and am also using the UICatalog sample app to stress ObjectAlloc (in Leaks). With that app, fire up every page except 'web' and watch the memory keep growing... then bring up the Web View Controller and kaboom! The kaboom part is NOT reproducible with Leaks running with the Simulator, though memory piles up to some high water point and appears to stabilize.Why, for example, is the ImageView in UICatalog still have active references laying around after being popped? No autorelease used.
Steve