user444854
user444854

Reputation:

Autorelease Drowning

I came across a problem that seems to be called "drowning" in autorelease pools.

My code creates and destroys objects correctly. However, I use some class methods that autorelease several variables without my knowing about it. Considering they loop thousands and thousands of times every minute... I find myself drowning in thousands of unreleased objects lost somewhere in the program.

2 questions:

  1. So either I do not use class methods AT ALL - is that a permanent solution, or, even so, will some instance methods (Foundation, UIKit) still autorelease objects without my knowing about it?

  2. or I can alloc an autorelease pool prior to calling class methods and draining it after calling the class methods - would this be a permanent solution?

Upvotes: 0

Views: 279

Answers (2)

dreamlax
dreamlax

Reputation: 95335

Dave DeLong has already answered your questions, but usually the only times when you fill the pool too high is when you're in a very tight loop. In this case, just create another autorelease pool for each iteration of the loop.

for (NSUInteger i = 0; i < 1000000000; i++)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // do the work

    [pool release];
}

Objects are automatically added to the most recently created autorelease pool for the current thread. By creating one for each iteration of the loop, you can get rid of the unwanted objects quickly rather than letting them pile up in the run loop's pool.

Upvotes: 1

Dave DeLong
Dave DeLong

Reputation: 243146

  1. Just because you don't use a class method doesn't mean you're going to avoid autoreleased objects. For example: NSString * path = [anotherString stringByAppendingPathComponent:@"foo"] returns an autoreleased object, yet no class methods were involved. As far as I know, the only way to avoid autoreleased objects is to not use objects. If you really want to go that route, check out CoreFoundation. (I do not recommend going that route.)

  2. If you do have some crazy factory method that creates tons of autorelease pools, then I'd probably do something like this:

    + (id) crazyFactoryMethodWithFoo:(id)foo {
      NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
      id returnValue = nil;
      //generate gobs of autoreleased objects
      returnValue = [something retain];
      [pool release];
      return [returnValue autorelease];
    }

    By explicitly retaining the return value before draining the pool, you ensure that the return value will live beyond the destruction of the autorelease pool. You then balance that retain by autoreleasing the return value and returning it.

Upvotes: 1

Related Questions