This loop leaks memory:
int64_t i,verylongnumber;
//misc. code
for(i=0;i<verylongnumber;i++){
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:
[NSNumber numberWithLongLong:65535],
[NSNumber numberWithLongLong:65535],
[NSNumber numberWithLongLong:65535],
[NSNumber numberWithLongLong:65535],
nil];
[myArray removeAllObjects];
[myArray release];
}
I've tried everything to keep it from leaking memory, but I can't. I think it has something to do with the NSNumbers. I assume they are created autoreleased, but does that mean I have to free them individually (i.e. use alloc)? How would I even do that? Create a separate variable for each NSNumber and insert that into the array? That seems like a lot of work. I tried [myArray removeAllObjects], but that made no difference. it is within my own thread with its own autorelease pool. I'm not sure if that makes a difference.
This fixed it:
I added an additional autorelease pool inside the loop:
int64_t i,verylongnumber;
//misc. code
for(i=0;i<verylongnumber;i++){
NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:
[NSNumber numberWithLongLong:65535],
[NSNumber numberWithLongLong:65535],
[NSNumber numberWithLongLong:65535],
[NSNumber numberWithLongLong:65535],
nil];
[myArray release];
[pool2 drain];
}
I'll take a stab at this..
You can remove [myArray removeAllObjects] as it is redundant. NSArray's do retain their objects, but they also release them when the array itself is deallocated.
The NSNumbers themselves are autoreleased. However if you do a very very large loop then that autoreleased memory won't actually be freed until the for loop exits and eventually the run loop as well (unless you have setup a separate NSAutoreleasePool somewhere).
So I can see how the memory usage would increase as this loop iterates, but at completion it should free the memory. How did you arrive at the conclusion that you have a leak?
Are you waiting to see if the objects get released in the near future?
Autoreleased objects are released at some point in the near future. In the case above, you're looping a very long number of times creating many objects. They will not get released within the scope of that code.
In a GUI app it means after the function returns when the run loop is being run. In a console app, it's when the pool is released.
Check out:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
Autorelease pools provide a mechanism whereby you can send an object a “deferred” release message.
The key is the deferred point.
EDIT: (after comment)
Note that you can drain the pool. The other option is to create non-autoreleased numbers (alloc/init) and explicitly release in your long running loop. depending on the code, that may be desirable since draining the pool could release objects deferred for release which code later in that loop/scope assumes is still deferred. If you want to control it, then control it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With