The release pool

Member
Posts: 241
Joined: 2008.07
Post: #1
I was hoping someone could shed some light on how the NSAutoreleasePool works.

I understand:

* Use of Cocoa such as [NSString stringWithString:@"Yo"], creates a string that will be autoreleased.
* I also understand that [[[MyObject alloc] init] autorelease], does also queue this object with the autorelease pool.

The question I have is, when is this object queued with the pool? Hopefully it's when the "autorelease" method is invoked, because that's what would make the most sense. I'm just a little unsure because I don't know where or how the autorelease pool is linked to these objects that I'm creating with autorelease.

The reason I'm concerned is, would code like this, cause a leak:

Code:
for(int i=10;i<10;i++)
{
     NSString* aString = [NSString stringWithFormat:@"String %d", i];
     // OR
     MyObject* anObject = [[[MyObject alloc] init] autorelease];
     [anObject doSomething:i]; // Just something.
}

The reference material for NSAutoreleasePool doesn't clarify it very well. The only code that uses the pool that I have is:

Code:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];

I just don't see how this is linked to anything that would actually release any object that calls autorelease. I would guess that NSObject has something in it so that the autorelease does what it's supposed to, but if it's in NSObject, and the autoreleasepool doesn't have any link to it (that I can tell), AND, there is no call to drain anywhere, it just doesn't make sense to me.

I'm coding for the iPhone SDK, so garbage collection is not enabled.

Any light on this is appreciated.
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #2
You have one current autorelease pool per thread. I assume that means that it's stored using thread local storage. So basically a global variable, but one that is unique for every thread. The object is added to the pool as soon as you call autorelease.

The simple act of doing [[NSAutoreleasePool alloc] init] creates a new pool and makes it active. When you release the pool, the previous pool is used again. That's why your main function of most Cocoa programs looks like something this:

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

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #3
There's nothing in the run loop that drains the pool...
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #4
Well that is just the autorelease pool that catches everything that the app might allocate. The application's run loop creates and releases a pool each time through as well.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
⌘-R in Chief
Posts: 1,253
Joined: 2002.05
Post: #5
AFAICT, the autorelease pool around UIApplicationMain is totally unnecessary. It's certainly not needed on the Mac, and not having one on the phone produces no warnings (in my testing).

I wonder why it's there at all, except incase someone adds some object creation to main()...
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
My recollection is that it's there to prevent warnings for autoreleased objects allocated before UIApplicationMain starts its run loop, since they'd otherwise be leaked...which is a bit silly, because a leak isn't particularly different from objects just sitting in an autorelease pool that never gets drained.
Quote this message in a reply
⌘-R in Chief
Posts: 1,253
Joined: 2002.05
Post: #7
Well on the Mac, it would log warnings about them being leaked, but on the phone, I don't see any messages about it, which makes me think that, like on the Mac, it really isn't necessary for that pool to be there.
Quote this message in a reply
Member
Posts: 27
Joined: 2008.12
Post: #8
bmantzey Wrote:The question I have is, when is this object queued with the pool?

Can you clarify what you mean by "queued with?" When you send an autorelease message the object gets added to a list of objects in the most recent autorelease pool. Each of those objects will get a release message when the pool is drained. There is a new pool created for each event that your app gets - like applicationDidFinishLaunching or touchesMoved - and drained at the end of the event, so you have until the end of the current event to use your object.

Of course if you retain the object it will stick around longer than that.

Quote:The reason I'm concerned is, would code like this, cause a leak:
Code:
for(int i=10;i<10;i++)
{
     NSString* aString = [NSString stringWithFormat:@"String %d", i];
     // OR
     MyObject* anObject = [[[MyObject alloc] init] autorelease];
     [anObject doSomething:i]; // Just something.
}

No leaks there. The method stringWithFormat returns an object that is already in the autorelease pool. You're adding anObject to the pool yourself, so it will get a release message when the pool is drained at the end of this event.

Here's the wrong way to do it:
Code:
for(int i=10;i<10;i++)
{
     NSString* aString = [NSString stringWithFormat:@"String %d", i];
     [aString retain]; //oops - now aString will not get deallocated. Leak.

    
     MyObject* anObject = [[[MyObject alloc] init] autorelease];
     [anObject doSomething:i];
     [anObject release]; //oops - this probably destroyed anObject, but
     //it's still in the pool. I'll crash when the pool tries to release an
    //invalid pointer.
}

-- Available Now: Dead Panic, a casual zombie shooter!
-- Development Blog: How to make a game under $1k
-- Twitter: xsmasher
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #9
That pretty much answers my question. By "when is it queued", I meant when is it added to the release pool, which is probably either a queue or a list internally. Anyway, yeah, it happens when you call autorelease. Thanks!
Quote this message in a reply
Post Reply