Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Main autorelease pools only releases when app closes?


int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}


This main autorelease pool that handles all my autoreleased objects in the main thread, does it only release its objects when my app is finished?

If that's the case, then can't my app crash if the user uses it for a long time since those autoreleased objects are only released when the app finally closes?

Thanks

Message was edited by: applehund

macbook, Mac OS X (10.5.4)

Posted on Sep 22, 2008 12:11 AM

Reply
16 replies

Sep 22, 2008 3:46 AM in response to applehund

Hi,

the release does not mean that your unreferenced objects will release. It means the Pool-object will be released.
As far as i understood the objects will be released each time the runloop is entered.

I forget to retain some objects in one of my apps some weeks ago and they were definitely release beause i got some realy strange efects. 🙂

Sep 22, 2008 10:55 AM in response to just.do.it

I don't quite understand.

Basically my question boils down to:

"Do autoreleased objects still stay in memory until their autoReleasePool is released?"

Because that would mean that if the user had my app open for a long time, it would eventually crash since I'm always allocating and autoreleasing objects and they wouldn't be released until the app closed.

Thanks

Sep 22, 2008 11:04 AM in response to applehund

applehund wrote:

Basically my question boils down to:

"Do autoreleased objects still stay in memory until their autoReleasePool is released?"


If they did don't you think that would be a pretty big problem for every Cocoa application ever written? Objects are deallocated on the next trip through the run loop after their reference count reaches 0. This is all extremely well documented.

Sep 22, 2008 12:14 PM in response to orangekay

I understand that it would be a big problem for all Cocoa applications and I know it's handled, but I want to understand it a bit more.

{quote}You add an object to an autorelease pool so it will receive a release message—and thus might be deallocated—when the pool is destroyed.{quote}

This is in the docs, so how do autoreleased objects get their reference count to 0 if they are only sent a release message when the pool is destroyed?

Doesn't this mean that when the main() autoreleasepool is destroyed, only then do all the autoreleased objects get released?

{quote}Objects are deallocated on the next trip through the run loop after their reference count reaches 0.{quote}

I'd understand this more if I knew how their reference count got to 0 before the main() autorelease pool was released.

Thanks

Sep 22, 2008 12:40 PM in response to applehund

As the documentation states, objects created with a pool on the pool stack are only released when that pool is released. Following this logic leads to the conclusion that there are a number of objects that will only be reclaimed when the application exits. Remove the autorelease pool lines in main.m to see the objects leaked in the console window - there are only a handful of objects that are leaked and the leak messages stop shortly after the application starts. This is probably the point where the Cocoa runloop pool is put in place.

I believe the pool in main.m is put in place to avoid the warnings that will ensue between the time the application starts up and the Cocoa runloop is put in place. Now at the beginning of that main runloop within Cocoa an autorelease pool is allocated - it is released and reallocated each time around the main run loop. This takes care of the objects autoreleased by an application in the general case.

I have not seen the source Cocoa source code but this explanation makes the most sense to me given all the evidence.

Sep 22, 2008 1:00 PM in response to Xanthos

What evidence would this be?


// Evidence.h
#import <Cocoa/Cocoa.h>
@interface Evidence : NSObject {
}
@end



// Evidence.m
#import "Evidence.h"
@implementation Evidence
- (void) dealloc
{
NSLog(@"Evidence go bye bye");

[super dealloc];
}
@end



// MyDocument.m
#import "MyDocument.h"
#import "Evidence.h"
@implementation MyDocument
- (id)init
{
self = [super init];
if (self) {

Evidence *debunker = [[[Evidence alloc] init] autorelease];

}
return self;
}


Output log:


[Session started at 2008-09-22 12:57:11 -0700.]
2008-09-22 12:57:12.327 Evidence[49785:10b] Evidence go bye bye
The Debugger has exited with status 0.


Note that the object was destroyed well before the application exited. Pools can be drained at any time.

Sep 22, 2008 3:16 PM in response to orangekay

Orangekay can you point me to the document that tells me that "Pools can be drained at any time"? From what I have read it only happens at very well defined points, namely when the pool is destroyed. Remember that in Cocoa Touch drain == release for pools.

As to your snippet - I think you missed the point of the discussion. It is expected that once UIApplicationMain is called there is a Cocoa supported run loop in place that will clean up its own pools. I suspect you created the MyDocument object after the Cocoa run loop was set up in which case Cocoa is cleaning up after you as expected. Or perhaps you were running in a garbage collected environment in which case there is no need for autorelease pools.

The claim is that the pool created outside the Cocoa run loop will not be cleaned up until it is released since the rules outlined in the documents on autorelease pools are followed. As further evidence try running the following as a Cocoa Touch application.


#ifndef TARGETOSIPHONE
#import <Cocoa/Cocoa.h>
#endif
@interface Evidence : NSObject
{
}
@end
@implementation Evidence
- (id) init
{
if (self = [super init])
{
NSLog(@"Evidence lives");
}
return self;
}
- (void) dealloc
{
NSLog(@"Evidence has been autoreleased");
[super dealloc];
}
@end
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Evidence *debunker = [[[Evidence alloc] init] autorelease];
#if TARGETOSIPHONE
int retVal = UIApplicationMain(argc, argv, nil, nil);
#else
int retVal = NSApplicationMain(argc, (const char **) argv);
#endif
[pool release];
return retVal;
}

Sep 22, 2008 3:30 PM in response to Xanthos

Xanthos wrote:
As to your snippet - I think you missed the point of the discussion. It is expected that once UIApplicationMain is called there is a Cocoa supported run loop in place that will clean up its own pools. I suspect you created the MyDocument object after the Cocoa run loop was set up in which case Cocoa is cleaning up after you as expected. Or perhaps you were running in a garbage collected environment in which case there is no need for autorelease pools.


Yup; an actual Cocoa application has no such forced instantiation in main.m. Clearly whatever behavior you're seeing is something that was cooked up for the iPhone which I have no experience with whatsoever. Nevertheless, I would not expect to see autoreleased objects accumulate indefinitely under any circumstances that could be considered normal on either platform.

Sep 22, 2008 5:25 PM in response to orangekay

By default a developer isn't required to create a pool.

From the iPhone Programming Guide. p 72
Objects released using the autorelease method stay in memory until you
explicitly drain the autorelease pool or until the next time around your event
loop.
...
Whenever possible, avoid using the autorelease method when you
can instead use the release method to reclaim the memory occupied by the
object immediately. If you must create moderate numbers of autoreleased
objects, create a local autorelease pool and drain it periodically to reclaim the
memory for those objects before the next event loop.

p. 87
When an application starts running in iPhone OS, the operating system calls the standard entry point:
the main function. The main function must always do three things:
1. Create a top-level autorelease pool.
2. Call the UIApplicationMain function.
3. Release the autorelease pool after UIApplicationMain returns.

My reading of this is the top level pool accumulates anything you don't assign to your own pools.
It's not released until the app quits but it will drain on every event loop.

Sep 22, 2008 9:48 PM in response to Scott Squires1

Scott Squires1 wrote:
It's not released until the app quits but it will drain on every event loop.


The second half of your sentence contradicts the first half. You should understand that drain == release. It does not seem plausible that Cocoa Touch is going to reach out and release the top level pool behind your back. You allocated it and you own it - that is the Cocoa model. Cocoa Touch creates its own pool each time through its event loop and at the bottom of the loop it drains (releases) its pool(s). Read the docs on threading and operations and you can see examples of this pattern.

So this means that the objects that Cocoa Touch puts into that pool before it gets its run loop pool in place are held hostage for the duration of the application. From the look of them I'm guessing that these are things related to loading the main nib file but who knows.

It is interesting to note that Cocoa does not require the top level pool in main.m like Cocoa Touch does.

Sep 22, 2008 10:35 PM in response to Xanthos

That's just it. It's the default template setup.

From the iPhone Programming Guide. p 72
Objects released using the autorelease method stay in memory until you
explicitly drain the autorelease pool or until the next time around your event
loop.

Every time through the event loop the autorelease pool is drained. Not released. Automatically.
Otherwise memory allocation would accumulate and there would be no need to retain any of the autorelease items. If they only were released when the app ended there would be no autorelease elements.

If you add code to the template and use a convenience allocation that object will be released the next time through the event loop.

Also remember you don't make your own event loop but it still happens.

Sep 23, 2008 8:53 AM in response to Scott Squires1

Scott, you have missed important details in your research and made invalid assumptions. Before you post please make a better attempt to know the subject matter. Read the rest of the documentation, not just the programming guide. The programming guide can be thought of as a summary for those new to iPhone programming. If you want to understand this you will have to dig a little deeper.

What you may learn is that *drain == release* on the iPhone. So yes every time through the event loop a pool is created and the one in place released. In other words alloc is called at the top of the loop and release / drain is called at the bottom. Work with threads and operations in Cocoa and you will learn to recognize this pattern. Learn what a run loop looks like.

For your next post I suggest you run my sample code above and explain to us why the the debunker object allocated in main is never de-allocated, even though it is added to the auto release pool in main.m by virtue of autorelease being called there.

Also, please read this thread more carefully. There is no need to remind us of what has already been stated.

Sep 23, 2008 10:58 AM in response to Scott Squires1

{quote}Whenever possible, avoid using the autorelease method when you
can instead use the release method to reclaim the memory occupied by the
object immediately.{quote}

This sounds like good practice -- just wondering though if everyone could chime in about how much this affects performance. Is this what you guys normally try to do, ie not use autorelease but manually release objects when possible?

I ask this because I use autorelease constantly throughout my code and want to know if you recommend going back through and replacing those with release statements.

This is a good discussion everyone, thanks, I've already learned quite a bit.

Main autorelease pools only releases when app closes?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.