Autorelease pools in Objective-C - release main AutoreleasePool?
Asked Answered
J

2

7

By my understanding, when an object is sent an autorelease message, if no autorelease pools exist other than the one in main.m, the object gets placed in the one in main.m. Assuming this is correct, I have a couple of questions:

1) Do all autoreleased objects stay in that pool until the termination of the app?

2) If 1 is true, does creating an autoreleased object without a local autorelease pool (therefore placing that object in the main.m pool) keep that object in memory until termination of the app or a memory warning is received?

3) When is the main.m autorelease pool drained, other than when the app receives a memory warning or the application is terminated?

For example, in a cellForRowAtIndexPath delegate method such as this:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Foobar"];
if (cell == nil) {
    // No cell to reuse => create a new one
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Foobar"] autorelease];

    // lots of custom stuff
}

return cell;

when are the cells actually released? They have to be autoreleased, because you can't release them before you return them, and you can't release them after, because they are out of scope. By my current understanding, the cells are placed in the topmost autorelease pool, and released when that pool is drained/released. In this case, that would be the only autorelease pool in the application; the one in main.

4) The problem with this it that even when I am done with those cells and the view controller has been released, the cells stay in memory, yes? If this is not the case, could someone provide an explanation of how the memory management in this situation really works? Thanks!

Note: I have looked at Apple's documentation, but it talks mostly about when to use your own local autorelease pools, but not much about how they actually function.

Jennie answered 18/12, 2011 at 3:55 Comment(0)
P
6

1) Do all autoreleased objects stay in that pool until the termination of the app?

Autoreleased objects by definition are owned by their autorelease pool until that pool is drained. When you send -autorelease to an object, that object is added to a list of objects that the pool will release later. Autorelease pools are organized in a stack, with the pool at the top of the stack being the pool to which any objects sent -autorelease are added. The pool created in main() is generally not the one at the top of the stack. For example, the run loop will create an autorelease pool at the beginning of each iteration.

2) If 1 is true, does creating an autoreleased object without a local autorelease pool (therefore placing that object in the main.m pool) keep that object in memory until termination of the app or a memory warning is received?

It would if the pool created in main() were the topmost pool, but as described above, that usually won't be the case.

3) When is the main.m autorelease pool drained, other than when the app receives a memory warning or the application is terminated?

There's no difference between the pool created in main() and any other autorelease pool. They're all drained when the pool is released, or at the end of the block if you used the @autorelease directive.

Percentile answered 18/12, 2011 at 4:56 Comment(6)
Hmm... I was pretty wrong. About a lot of stuff! Thanks for shedding some lightJennie
"Autoreleased objects by definition are retained by their autorelease pool" This is incorrect. Autorelease pools don't retain anything. Autorelease is nothing but a delayed message mechanism. When you send -autorelease to an object, it does not increase its retain count. It adds the object to a list of objects that will be sent a -release message when the autorelease pool itself is released or sent a -drain message.Houseline
A couple of additional points: (1) Autorelease pools are per thread and, thus, an autoreleased object can never be passed between two threads safely. (3) The top level pool is likely never drained because there is no point; if an app is being terminated, it'll send out the final "i'm outta here" notifications and then exit() directly without bothering to drain the pool.Nautilus
@Houseline You're right -- poor choice of words. Perhaps 'owned' would be a better word, as the autorelease pool essentially assumes responsibility for releasing an autoreleased object.Percentile
No, "owned" isn't a good choice either. Newcomers to Cocoa and Cocoa touch are often confused, and have an idea that an autorelease pool is conceptually similar to the heap. Perhaps Apple should have called them something like an "Autoreleaser" and left the word "pool" out of it.Houseline
i have one question. According to the discussion an autorelease pool is created with each thread. Suppose i comment the @autorelease directive in main. So UIApplicationMain() will create an autorelease pool. Now if this is the case then why would we create an autorelease pool before UIApplicationMain() and what objects will be there in that autorelease pool?Paleobotany
C
8

From the documentation:

The Application Kit creates an autorelease pool on the main thread at the beginning of every cycle of the event loop, and drains it at the end, thereby releasing any autoreleased objects generated while processing an event. If you use the Application Kit, you therefore typically don’t have to create your own pools. If your application creates a lot of temporary autoreleased objects within the event loop, however, it may be beneficial to create “local” autorelease pools to help to minimize the peak memory footprint.

So, autoreleased objects in the default pool will only survive the duration of the current event.

Charitycharivari answered 18/12, 2011 at 4:16 Comment(0)
P
6

1) Do all autoreleased objects stay in that pool until the termination of the app?

Autoreleased objects by definition are owned by their autorelease pool until that pool is drained. When you send -autorelease to an object, that object is added to a list of objects that the pool will release later. Autorelease pools are organized in a stack, with the pool at the top of the stack being the pool to which any objects sent -autorelease are added. The pool created in main() is generally not the one at the top of the stack. For example, the run loop will create an autorelease pool at the beginning of each iteration.

2) If 1 is true, does creating an autoreleased object without a local autorelease pool (therefore placing that object in the main.m pool) keep that object in memory until termination of the app or a memory warning is received?

It would if the pool created in main() were the topmost pool, but as described above, that usually won't be the case.

3) When is the main.m autorelease pool drained, other than when the app receives a memory warning or the application is terminated?

There's no difference between the pool created in main() and any other autorelease pool. They're all drained when the pool is released, or at the end of the block if you used the @autorelease directive.

Percentile answered 18/12, 2011 at 4:56 Comment(6)
Hmm... I was pretty wrong. About a lot of stuff! Thanks for shedding some lightJennie
"Autoreleased objects by definition are retained by their autorelease pool" This is incorrect. Autorelease pools don't retain anything. Autorelease is nothing but a delayed message mechanism. When you send -autorelease to an object, it does not increase its retain count. It adds the object to a list of objects that will be sent a -release message when the autorelease pool itself is released or sent a -drain message.Houseline
A couple of additional points: (1) Autorelease pools are per thread and, thus, an autoreleased object can never be passed between two threads safely. (3) The top level pool is likely never drained because there is no point; if an app is being terminated, it'll send out the final "i'm outta here" notifications and then exit() directly without bothering to drain the pool.Nautilus
@Houseline You're right -- poor choice of words. Perhaps 'owned' would be a better word, as the autorelease pool essentially assumes responsibility for releasing an autoreleased object.Percentile
No, "owned" isn't a good choice either. Newcomers to Cocoa and Cocoa touch are often confused, and have an idea that an autorelease pool is conceptually similar to the heap. Perhaps Apple should have called them something like an "Autoreleaser" and left the word "pool" out of it.Houseline
i have one question. According to the discussion an autorelease pool is created with each thread. Suppose i comment the @autorelease directive in main. So UIApplicationMain() will create an autorelease pool. Now if this is the case then why would we create an autorelease pool before UIApplicationMain() and what objects will be there in that autorelease pool?Paleobotany

© 2022 - 2024 — McMap. All rights reserved.