Search code examples
objective-cautomatic-ref-countingautorelease

Objective C - autoreleasepool and ARC leak memory


In my understanding, if ARC is enabled, objects inside @autoreleasepool{} should be released when they are not used anymore.

However, the code

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        for (int i = 0; i < 1000000000; i++) {
            NSString *string = @"ab c";
            NSArray *array = [string componentsSeparatedByString:string];
        }
    }
    return 0;
}

leaks memory.

Instruments show that leaked objects are __NSArrayM created by -[NSString componentsSeparatedByString:]

So, the question is: why __NSArrayM objects are not being destroyed in the same loop iteration they are created?

Could anyone help me in solving this problem

Update: Thanks for the answers, it seems I used the term "memory leak" incorrectly, and misunderstood how @autoreleasepool{} works. To resolve the problem, I should have placed @autoreleasepool{} inside the for-loop.


Solution

  • To understand how autorelease works, compare this code below to your original:

    for (int i = 0; i < 1000000000; i++)
    {
        @autoreleasepool
        {
            NSString* string = @"ab c";
            NSArray* array = [string componentsSeparatedByString:string];
        }
    }
    

    Auto-released objects are marked for release when they go out of scope, but not actually released until the end of the autorelease section (which is where the autorelease pool gets drained). So the code above will release the marked objects every time around the loop whereas your original code would only release them all at the end of the loop.

    Auto-release pools can be nested, the closest one is used when an object is autoreleased. This allows you to return objects from functions like [NSString stringWithFormat:@"%d", i]; - the returned string has a retain count of 1 but is marked for auto-release - you can use it temporarily, but if you need to keep it for later use you need to retain it (which happens when you assign it to a strong reference). So when you retain it, the retain count goes to 2, then later when it is auto-released the retain count goes to 1 and all is good. If you never retain it then when auto-released the retain count goes to 0 and the object is dealloced.