Autorelease pools

Member
Posts: 73
Joined: 2009.03
Post: #1
Up to this point, I haven't been using autorelease pools at all. Is there a recommended best practice for using them? For example, if I create a temporary object inside a function, should it use autorelease with a pool that drains at the end of the function?

I've been developing with automatic garbage collection in mind, thinking that if I don't specify "retain", then the memory will automatically be freed when the pointer goes out of scope and garbage collection happens. Is this correct or should I be using autorelease pools for stuff like that?
Quote this message in a reply
Moderator
Posts: 613
Joined: 2004.09
Post: #2
The iPhone doesn't support Garbage Collection, I assume you are developing for the iPhone being that this is in the iPhone forum.

Kyle Richter
DragonForged.com
Twitter: @kylerichter
Quote this message in a reply
⌘-R in Chief
Posts: 1,237
Joined: 2002.05
Post: #3
Unless you spawn secondary threads, or use a hard loop that never exits until your app quits (ie while (1) { ...}) in the main thread, you never need to create an autorelease pool; You just need to use proper memory management (retain/release/autorelease correctly).
Quote this message in a reply
Member
Posts: 73
Joined: 2009.03
Post: #4
FreakSoftware Wrote:Unless you spawn secondary threads, or use a hard loop that never exits until your app quits (ie while (1) { ...}) in the main thread, you never need to create an autorelease pool; You just need to use proper memory management (retain/release/autorelease correctly).

From what I understand, autorelease is used WITH autorelease pools. If I never create an autorelease pool, is there any reason to use autorelease?

What about Kodex's comment about the iPhone not having garbage collection? If that is true, then I would think that every object needs to be released. If that is true, then using an autorelease pool seems like the best way to go for objects of limited scope. Is this the correct answer to my original question?
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #5
The main thread has an autorelease pool which is allocated for you because the OS needs it for many objects that it uses (Cocoa operates in the main thread). IOW, you don't have to autorelease anything, but it does, so there's an autorelease pool by default in the main thread.
Quote this message in a reply
⌘-R in Chief
Posts: 1,237
Joined: 2002.05
Post: #6
Gillissie Wrote:From what I understand, autorelease is used WITH autorelease pools. If I never create an autorelease pool, is there any reason to use autorelease?

Like Jake said, the main thread already has an autorelease pool created for you. You can/should/will use autorelease all over the place, but you don't need to create a pool yourself, except in the conditions previously mentioned.

Quote:What about Kodex's comment about the iPhone not having garbage collection? If that is true, then I would think that every object needs to be released.

Naturally.


Quote:If that is true, then using an autorelease pool seems like the best way to go for objects of limited scope.

Yes. But you don't need to do it in every function. Once per event-loop cycle is good enough, and that's already handled for you. In extreme cases if you're allocating millions of objects in a loop, you can create an autorelease pool within that loop so your memory usage is consistently low, but that's pretty rare. It certainly would be in a game that uses a timer, for instance.
Quote this message in a reply
Moderator
Posts: 613
Joined: 2004.09
Post: #7
Gillissie Wrote:What about Kodex's comment about the iPhone not having garbage collection? If that is true, then I would think that every object needs to be released. If that is true, then using an autorelease pool seems like the best way to go for objects of limited scope. Is this the correct answer to my original question?

Yes you must manually retain/release objects on the iPhone. And with very limited memory availability it is vital to be careful with this step.

Check out the clang static analyzer, to see where you are making mistakes.

Kyle Richter
DragonForged.com
Twitter: @kylerichter
Quote this message in a reply
Member
Posts: 73
Joined: 2009.03
Post: #8
Thanks all for the additional info. I couldn't find this kind of info in the SDK help.
Quote this message in a reply
Moderator
Posts: 613
Joined: 2004.09
Post: #9
Gillissie Wrote:Thanks all for the additional info. I couldn't find this kind of info in the SDK help.

Make sure you supplement the iPhone SDK docs with the Objective C 2.0 docs as well.

Kyle Richter
DragonForged.com
Twitter: @kylerichter
Quote this message in a reply
Member
Posts: 306
Joined: 2009.03
Post: #10
Something that wasn't mentioned here that maybe should is when to use autorelease. From my understanding, the best time to use it is when you are creating something and you want to hand it off in your return value(but not use it yourself). An example is [NSMutableArray array]. It creates an empty array with autorelease.
Otherwise you should be using release immediately to get that memory freed up, and to also make debugging easier since errors that occur in destruct from an autorelease are harder to figure out. So moral of the story is most of the time you want to release, not autorelease. Please correct me if somebody feels I am mistaken about this.
Quote this message in a reply
Moderator
Posts: 613
Joined: 2004.09
Post: #11
Especially on the iPhone you really want to avoid autorelease as it can tie up the memory for a bit too long. Try to use release as much as possible.

Kyle Richter
DragonForged.com
Twitter: @kylerichter
Quote this message in a reply
Member
Posts: 73
Joined: 2009.03
Post: #12
Ok, I found an example in the SDK docs that confuse me on this subject.

Code:
NSString *soundFilePath =
                [[NSBundle mainBundle] pathForResource: @"sound"
                                                ofType: @"wav"];

NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];

AVAudioPlayer *newPlayer =
                [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
                                                       error: nil];

[fileURL release];

self.player = newPlayer;

[newPlayer release];

[self.player prepareToPlay];
[self.player setDelegate: self];

In this snippet of code, you see three objects being created. One of them is never released (soundFilePath), one is released after using it (fileURL), and one is released after assigning it to another pointer (newPlayer). NONE of these specify retain or autorelease.

This seems especially confusing for the newPlayer one, since we definitely want to retain the object. What we might not be seeing is the @property declaration including (retain), but I don't know.

I am also especially confused by the soundFilePath object, since it doesn't seem to get released at all.
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #13
Gillissie Wrote:This seems especially confusing for the newPlayer one, since we definitely want to retain the object. What we might not be seeing is the @property declaration including (retain), but I don't know.
That's correct. The setter retains it, which is why you don't need to hold onto it anymore. You can test this by doing something like:

Code:
    NSLog(@"retains: %d", [newPlayer retainCount]); // should be 1
    self.player = newPlayer;
    NSLog(@"retains: %d", [newPlayer retainCount]); // should be 2
    [newPlayer release];
    NSLog(@"retains: %d", [newPlayer retainCount]); // should be back to 1

Gillissie Wrote:I am also especially confused by the soundFilePath object, since it doesn't seem to get released at all.

Right, this is standard Cocoa stuff. You are expected to know that if you call a method containing "init" then it is returned to you with a retain count of 1. If you call something without "init" in it then it is returned to you set to be autoreleased. So fileURL is created with initFileURLWithPath, which has "init" in it, so you know you have to release (or autorelease) it yourself. soundFilePath is created with pathForResource, which contains no "init" in the call and is thus returned to you as autoreleased.
Quote this message in a reply
Member
Posts: 73
Joined: 2009.03
Post: #14
Thanks for the additional info.

So what happens if you create a NSString object, then create another object using the same variable in the same scope? Does the first one still get autoreleased, or is it a memory leak? I would like to create several audio objects, and I would like to re-use the soundFilePath variable.
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #15
Yes, you can reuse it without any problem, it'll still be autoreleased. It'll only be a leak if you, or some other object, retains it and forgets to release it.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Is implementing autorelease code in constructor a good idea ? Bracer 4 2,704 Oct 13, 2009 12:41 PM
Last Post: SethWillits
  Track down an autorelease bug kendric 2 3,256 Jun 28, 2009 05:09 AM
Last Post: kendric