views:

39

answers:

2

Let's say I'm developing a game. I run the following class method thousands of times:

NSBundle *bundle=[NSBundle mainBundle];

I do not create an autorelease pool and release the objects that call the above class method all the time. I create an object, it calls the above class method, I release it, and on, and on, thousands of times.

3 questions:

  • Is memory leaked?
  • If I ran:

NSAutoReleasePool *pool=[[NSAutoReleasePool alloc] init]; [pool drain];

would it then effectively release all those NSBundles created in the class method?

  • if I wrote:

pool=nil;

instead of writing:

[pool drain];

Would the same effect be achieved? Is this good practice?

The three questions are correlated and I will boost the one that clarifies them :)

A: 
  1. No, memory is not leaked. [NSBundle mainBundle] returns an autoreleased object, so the autorelease pool will take care of it. However, if you're going to call it a bunch of times in one function or something, you'd be better off either getting a reference to it once and just holding on to it while you need it, or creating your own autorelease pool.
  2. Not exactly. Everything after NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; that is autoreleased will go into pool, and after you drain the pool, they'll be released. Note: [pool drain]; also releases the pool, so don't call [pool drain]; [pool release]; or you will send the release message to the object twice and probably crash.
  3. No. pool = nil; would just lose the reference to pool and the actual pool object would be leaked. You have to call either [pool drain]; or [pool release]; and good practice would be to set pool = nil; afterwards.
anshuchimala
@anshuchimala: 1. So what you are saying is that memory is not leaked, but it's not released either? My pool after a thousand calls to that class method would have a thousand objects waiting for autorelease? 2. Yeah I edited the question already, thanks. But let me try to understand: when NSBundle autoreleases the object it returns, it goes automatically to the pool I created before? (let's say I created a pool by writing NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] before calling the class method on NSBundle) 3. Got it, thanks.
GSchv
1. Right, when you `autorelease` something, you relinquish ownership of it, but it sticks around until whatever autorelease pool now has ownership of it drains.2. Yeah. Here, the documentation might be able to explain it better than I can: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047 (read the part about the scope of autorelease pools and nested pools).
anshuchimala
+1  A: 

If you do not create an autorelease pool, and one does not already exist, any objects that are autoreleased (either by you, or by other libraries you are using) will be leaked.

setting pool=nil; does nothing except leak the whole pool, perhaps if the pool was set in a property i.e.

 @property(nonatomic, retain) NSAutoreleasePool *pool;

 self.pool = [[[NSAutoreleasePool alloc] init] autorelease];

 //now, self is the sole retainer of pool, so if self abandons it it gets drained:

 self.pool = nil;

 //pool's retain count drops to zero, pool drains.

If you are doing this thousands of times, it might slow things down to drain the pool every time, consider doing it every 5 or ten times, set a counter in the loop and when it hits some decided number, do this:

 self.pool = [[[NSAutoreleasePool alloc] init] autorelease];
 //this will get rid of the old pool and put in a new one, so you only have to get rid of the one remaining at the end of the loop.
Alex Gosselin