Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the consequences of omitting @autoreleasepool { } in main()?

Why do the Xcode 4.x templates for Objective-C command-line and iOS programs add the @autoreleasepool {} part wrapping main()'s code? Note that this doesn't happen for the OS X application template.

Why don't OS X applications do the same? Why don't both use the same method?

Finally, since all memory is released when any program exits, why is all of this of practical importance?


Or to ask it differently, what are the practical consequences of omitting @autoreleasepool { ... } in main() for a command line or an iOS Objective-C program?

These two pieces of code compile and seem to work equivalently:

1.

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSArray *array = @[@"Hello, world!"];
        NSLog(@"%@", array[0]);
    }
    return 0;
}

2.

int main(int argc, const char * argv[])
{
    NSArray *array = @[@"Hello, world!"];
    NSLog(@"%@", array[0]);
}

Note, I only care about the explanation in the ARC context. ARC forbids the explicit use of autorelease.

like image 574
Ricardo Sanchez-Saez Avatar asked Aug 24 '13 19:08

Ricardo Sanchez-Saez


1 Answers

autorelease doesn't work if there is no autorelease pool on the stack.

It's not really necessary to use autoreleased objects in objective-c (as you do in your examples), so you can omit it in theory, however most Apple frameworks do use autoreleased objects heavily.

Normally, every thread should have at least one autorelease pool, otherwise using any Obj-C code is very unsafe. Setting up an autorelease pool at the beginning of main is then a very good practice.

EDIT:

In ARC, although explicit autorelease is forbidden, autorelease calls are still there (added by the compiler). That implies the need for an autorelease pool.

This has nothing to do with releasing the memory. The very existence of an autorelease pool is necessary. Even if it isn't ever drained.

I guess that OS X doesn't add the autorelease pool to the template because the programmers can also use a garbage collector (although it is deprecated now).

EDIT 2:

Just created an OS X project and the @autoreleasepool is there. In fact, the only template without it is a "Core Foundation" project which is not really Obj-C, it's pure C.

EDIT 3: (After some more thinking and some googling)

With the introduction of ARC, autorelease pools were rewritten. When before they were a framework feature, now they are a language (Obj-C) feature. They are implemented differently. It seems that every new thread has an implicit autorelease pool now. Using @autoreleasepool doesn't actually create a new autorelease pool on some thread stack any more, it just puts a mark to the implicit autorelease pool (so that you can drain everything autoreleased after the mark). That means there is no way to create an example triggerring warnings or errors when @autoreleasepool is omitted.

However, this is considered to be an implementation detail, so it can be easily changed in future (or when another compiler is used!). That's why it's good practice to still set up an @autoreleasepool for every new thread (mentioned, for example, in -[NSThread detachWithSelector:..] documentation).

like image 56
Sulthan Avatar answered Sep 27 '22 21:09

Sulthan