Leif Leif - 6 months ago 53
iOS Question

Objective C / iOS: Memory release with ARC (memory leak)

I am new to

and I do not understand the release of memory correctly.
To test it, I created an empty
enabled iPhone-Project and created a very simple test class:

#import "MemTest.h"

@implementation MemTest {


-(void) start {
for (int i = 0; i < 1500000; i++) {
NSMutableString *myString = [NSMutableString string];

// The appended string is 2000 characters long in the real test class.
[myString appendString:@"12345678901234567890123456 <very long>"];

if (i % 1000 == 0) {
NSLog(@"i = %d", i);

myString = nil;


I simply start the test in the

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
MemTest *test = [[MemTest alloc] init];
[test start];


The application (as expected) prints many nice numbers "i = xy" but the memory usage increases with every iteration and finally the application crashes:

2012-12-06 20:17:40.193 MemTestApp[19250:11303] i = 930000
2012-12-06 20:17:40.208 MemTestApp[19250:11303] i = 931000
MemTestApp(19250,0xac63f2c0) malloc: *** mmap(size=16777216) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

So my question is: Why is the memory usage growing at all?

I thought by assigning nil, the memory should be released, when using
. What am I missing here?


A few things could be going wrong:

  1. You might not actually have ARC enabled. You should double-check that. Simplest way is to throw in a -retain in your code and make sure that throws a compiler error.

  2. ARC doesn't necessarily prevent objects from entering the autorelease pool. It tries to catch that if it can, but it doesn't make guarantees. Notably, at -O0 (no optimization), it frequently does not prevent objects from entering the autorelease pool. This is most likely what's going on for you.

  3. Even at higher optimization levels, ARC-enabled code is still not guaranteed to catch autoreleases.

If you stick an @autoreleasepool{} inside of your for loop you'll find the memory usage should go away. Alternatively, instead of using [NSMutableString string], you could try [NSMutableString new], which doesn't use the autorelease pool at all* but should otherwise behave identically in ARC code.

* well, NSMutableString is free to use the autorelease pool internally if it wants to