开发者

NSEnumerator memory leak

This leaks like mad, due to the way I use enumerators. Why? It leaks even more severely if I don't release the enumerator - I understand that much.. but I don't understand why this still leaks.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

   // insert code here...
   NSLog(@"Hello, World!");

   // Create an array and fill it with important data!  I'll need to enumerate this.
   NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:300];

   int i;
   for(i = 0; i < 200; i++)
     [myArray addObject:[NSNumber numberWithInt:i]];

   while(1)
   {
      NSEnumerator *enumerator = [myArray objectEnumerator];
      // Imagine some interesting code here
      [enumerator release];
   }

   // More code t开发者_如何转开发hat uses the array..

   [pool drain];
   return 0;
}


It doesn't leak, per se — and you shouldn't release the enumerator.

A memory leak is when memory is left allocated but can no longer be released (typically because you no longer have a pointer to it). In this case, the enumerator will be released when the autorelease pool drains, but you're preventing the program from reaching that line with your loop. That's why the enumerators pile up. If you change the loop to:

while(1)
{
    NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];
    NSEnumerator *enumerator = [myArray objectEnumerator];
    [innerPool drain];
}

you'll find that your memory consumption remains constant, because the enumerator will be properly released at the end of each iteration.


It leaks because your outermost autorelease pool only gets to do its thing once. Any autoreleased objects created within the while(1) loop will just sit around consuming memory until your program flow gets to the [pool drain] at the end.

To avoid this, create additional nested autorelease pools inside your loop, like this:

while(1) {
    NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];
    // .. Do a bunch of stuff that creates autoreleased objects
    [innerPool drain];
}

This approach is similar to how AppKit works, creating and draining a new autorelease pool for each iteration through its event loop.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜