You were bitten by a frightening pool of abstracts. In fact, so that MRC (manual reference counting) is controlled by people instead of immediately releasing the object, it can be transferred to the autofill pool ( NSAutoreleasePool instance, it contains additional information) that will save the object until the pool is later drained . ARC (automatic reference counting) can be designed so that automatic processing equipment is not necessary, but remains compatible with MRC.
The pool automatically merges at the end of the run cycle, i.e. when the application has finished processing the event. However, if the application creates many temporary objects and then discards them, this is some localized part of the program, then using a local pool of auto resources can significantly reduce the maximum memory usage. The point is not that such temporary objects will not be released, they simply will live much longer than necessary. A local pool can be created using the @autoreleasepool { ... } construct.
You can see the effect in your example by wrapping the whole body of applicationDidFinishLaunching:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { @autoreleasepool { ... } }
and going through the debugger.
In your real code, you need to return from the point that creates many temporary objects in order to find a suitable point for adding a pool of autoresists.
NTN.
Adding
These are not objects in your array that are not freed when you think they need it, you can check this using a simple class that considers initialization and freeing, for example:
@interface TestObject: NSObject
+ (void) showCounts; @end @implementation TestObject static uint64_t initCount = 0, deallocCount = 0; - (id) init { self = [super init]; if(self) initCount++; return self; } - (void) dealloc { deallocCount++; } + (void) showCounts { NSLog(@"init: %llu | dealloc: %llu", initCount, deallocCount); initCount = deallocCount = 0; } @end
Use this instead of NSObject and call showCounts after you showCounts done with your test - try with / without auto-repeat, etc.
Your memory is always freed, itβs just the time it is released, and this is the problem. Some objects fall into the autorun pool, either by default, which is omitted once per event, or local.
If you do not create many temporary objects in response to a single event, you will usually not see a problem. Think about whether you are pursuing a real problem for your application here. If you are among the things to try to alleviate the problem, follow these steps.
Avoid using convenience constructors like <name>WithX... , which are abbreviated values ββfor [[[C alloc] initWithX...] autorelease] . In many cases, but not in all cases, the compiler can delete such objects from the autocomplete pool right after the convenience constructor returns (and your case looks like one in which there may be a failure). It is better to use alloc / init , new (short for alloc / init ) or, if provided, newWithX... (short for alloc / initWithX... ). Try these options in your example and see the differences in when (and not if) memory is freed.
Well placed @autoreleasepool blocks.
NTN