Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > retain, release, autorelease (is this right?)

retain, release, autorelease (is this right?)
Thread Tools
swcrissman
Fresh-Faced Recruit
Join Date: Sep 2000
Status: Offline
Reply With Quote
Jun 6, 2001, 09:22 AM
 
Hey all. I just got through the Object ownership/management chapter in Learning Cocoa, and would like to verify my grasp on the system, as well as ask a few questions which I have.

My two main questions are:
How do you know when an autorelease pool will check its variables for release? In the book, an example in this basic format is given:
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
<font color = brown>// ObjA creates/inits ObjX</font>
<font color = brown>// ObjA returns [ ObjX autorelease ] to ObjB</font>
<font color = brown>// ObjB sends [ ObjX retain ]</font>
<font color = brown>// ObjB does stuff here...</font>
<font color = brown>// ObjB sends [ ObjX release ]</font>
</font>[/code]
I understand how the above example works, but how do you know that the pool will not release ObjX after it is autoreleased by ObjA, but before ObjB retains it?

Next question: Is an object's reference count used if it is not reelased into the autorelease pool? I am guessing no, as that seems like the whole point of having the pool in the first place, but I'm not sure... Here's a code sample to illustrate what I am asking:
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
<font color = brown>// Create/Init ObjX; // ObjX ref. count == <font color = blue>1</font></font>
[ObjX retain]; <font color = brown>// ObjX ref. count == <font color = blue>2</font></font>
[objX release]; <font color = brown>// ObjX ref count == <font color = blue>1</font>, but</font>
<font color = brown>// release is called on ObjX </font>
<font color = brown>// without it having ever been</font>
<font color = brown>// in the autorelease pool.</font>

<font color = brown>// POINT A: Is ObjX valid here???</font>
</font>[/code]

I also don't understand why you would create more than one autorelease pool, but I am guessing it has something to do with my first question about when the pools clean up after their objects. If someone wants to give an explanation of this, that'd be great, but I think if the first two questions are answered, I'll have a pretty good grasp on things.

Oh, also: do objects have a default copy message like C++ object have a default assignment operator, or must that message be created for every class you create (that has a potential to be copied).

Thanks!!

Spencer
     
sadie
Senior User
Join Date: Feb 2001
Location: Rochester, uk
Status: Offline
Reply With Quote
Jun 6, 2001, 12:26 PM
 
I always wondered this! My guess was that it has a fixed time delay or something. If anyone knows the answer, let us know!

IIRC, the reference count is always used, even when it's not in the autorelease pool.

(Sorry my reply wasn't more useful)
All words are lies. Including these ones.
     
honeydew
Dedicated MacNNer
Join Date: Apr 2001
Location: San Francisco, USA
Status: Offline
Reply With Quote
Jun 6, 2001, 05:09 PM
 
There is great Objective-C memory management article at Stepwise called Hold Me, Use Me, Free Me. I think this passage answers your autorelease question:
Now, a question might arise at this point. Who creates the release pool and how often does it get cleaned out? It turns out that in an Cocoa application, it is created automatically at the start of the internal event loop and is cleared out at the end. Of course, you can always create your own pool and dispose of it. This can be done to enhance performance and reduce a program's memory requirements if a certain operation is known to generate a large number of temporary objects that would otherwise clog the default release pool.
     
ali
Forum Regular
Join Date: Sep 2000
Status: Offline
Reply With Quote
Jun 6, 2001, 05:25 PM
 
Originally posted by swcrissman:
<STRONG>Oh, also: do objects have a default copy message like C++ object have a default assignment operator, or must that message be created for every class you create (that has a potential to be copied).
</STRONG>
They don't. To indicate you can be copied, you need to implement the NSCopying protocol, which involves implement the copyWithZone: method. (You can usually ignore the zone.)

Note that if you are an immutable object, you can implement copyWithZone: to simply do a [self retain].

Ali
     
ali
Forum Regular
Join Date: Sep 2000
Status: Offline
Reply With Quote
Jun 6, 2001, 05:29 PM
 
Originally posted by swcrissman:
Is an object's reference count used if it is not reelased into the autorelease pool? I am guessing no, as that seems like the whole point of having the pool in the first place, but I'm not sure... Here's a code sample to illustrate what I am asking:
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
<font color = brown>// Create/Init ObjX; // ObjX ref. count == <font color = blue>1</font></font>
[ObjX retain]; <font color = brown>// ObjX ref. count == <font color = blue>2</font></font>
[objX release]; <font color = brown>// ObjX ref count == <font color = blue>1</font>, but release is called on ObjX without it having ever been in the autorelease pool.</font>

// POINT A: Is ObjX valid here???</font>[/code]
The reference count is used even in the absence of autorelease pools! ObjX is valid at the point you indicated, because it still has a refcount of 1.

Ali

[ 06-06-2001: Message edited by: ali ]
     
swcrissman  (op)
Fresh-Faced Recruit
Join Date: Sep 2000
Status: Offline
Reply With Quote
Jun 7, 2001, 08:35 AM
 
Thanks ali, that's good to know. But that leaves me not understanding why to use autorelease then. If the reference count is always valid, why couldnt you call release rather than autorelease every time? Autorelease just seems to be saying, hold on to this for a little while, then delete it if its reference count is 0, while release is saying, delete this if its reference count is 0. Unless autorelease is just used for cased when the reference count will briefly be 0, but be retained shortly after being released, such as in my example in the first post. Is that it? Maybe.

Also, not sure when the 'end of the internal event loop' falls, exactly. I'm going to go read the article mentioned by honeydew (thanks!). Hopefully that will clear some things up...

Thanks very much for responding.

Spencer
     
ali
Forum Regular
Join Date: Sep 2000
Status: Offline
Reply With Quote
Jun 7, 2001, 12:34 PM
 
Originally posted by swcrissman:
If the reference count is always valid, why couldnt you call release rather than autorelease every time? Autorelease just seems to be saying, hold on to this for a little while, then delete it if its reference count is 0, while release is saying, delete this if its reference count is 0.
More strictly speaking, autorelease just says "send this object a release later". The place where autorelease is most useful is when you have to return a value from a method call, and you have to manufacture the value, but you don't want the caller to have to release it. (In general, this is the convention --- return values should not be freed by the caller except in the alloc, copy, and new.)

Your example from your first message is indeed a good use of the autorelease.

Another place where autorelease is used is in a setXXX: method, where you are getting rid of the earlier value. There the question of release vs autorelease comes up. One reason to use autorelease is to make things safer. Consider the following methods in an object:

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>- (NSString *)title {
<font color = green>return</font> myTitleInstanceVar;
}

- (<font color = green>void</font>)setTitleNSString *)newTitle { <font color = brown>/* Vers A */</font>
[myTitleInstanceVar release];
myTitleInstanceVar = [newTitle copy];
}

- (<font color = green>void</font>)setTitleNSString *)newTitle { <font color = brown>/* Vers B */</font>
<font color = green>if</font> (newTitle != myTitleInstanceVar) {
[myTitleInstanceVar release];
myTitleInstanceVar = [newTitle copy];
}
}

- (<font color = green>void</font>)setTitleNSString *)newTitle { <font color = brown>/* Vers C */</font>
[myTitleInstanceVar autorelease];
myTitleInstanceVar = [newTitle copy];
}</font>[/code]

Vers A is scary for two reasons. Problem 1: if newTitle == myTitleInstanceVar, releasing first will clobber the value. Problem 2: If someone asked for the title with the "title" method, then immediately set a new title, the old title will be released out from under them:

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
str = [obj title];
[obj setTitle:newTitle];
<font color = brown>/* str is now potentially invalid */</font></font>[/code]

Vers B solves the problem 1; but not 2. Vers C solves both, by lengthening the lifetime of the old title so anyone who asked for it will still have a valid, autoreleased reference.

Note that another way to solve problem 2 is to implement title this way:

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>- (NSString *)title {
<font color = green>return</font> [[myTitleInstanceVar retain] autorelease];
}</font>[/code]

Which way you choose depends on which is more likely to be called: the title method, or setTitle:?

Note that for performance reasons, for very low-level set/get situations, you would not want to use autorelease. Setting the title of an NSWindow is one thing (happens relatively infrequently), but you wouldn't want thousands of autoreleases to happen when you insert or remove objects in an NSArray. So in some cases the unsafe route (vers B) might be taken, and this is indicated in documentation... Of course with an NSArray or NSDictionary this makes sense, as it's a simple container for values you provide.

Also, not sure when the 'end of the internal event loop' falls, exactly. I'm going to go read the article mentioned by honeydew (thanks!). Hopefully that will clear some things up...
By default the "end of the event loop" is when the AppKit handles and dispatches events. I think AppKit does something like:

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>{
pool = [[NSAutoreleasePool alloc] init];
get and dispatch event
[pool release];
}</font>[/code]

Ali

[ 06-07-2001: Message edited by: ali ]
     
swcrissman  (op)
Fresh-Faced Recruit
Join Date: Sep 2000
Status: Offline
Reply With Quote
Jun 7, 2001, 02:09 PM
 
Ali,

Thanks again! Those examples were spot on. I understand completely now! Thanks for pretty much walking me through that.

Spencer
     
Angus_D
Addicted to MacNN
Join Date: Mar 2000
Location: London, UK
Status: Offline
Reply With Quote
Jun 9, 2001, 05:08 AM
 
You need another autorelease pool for every thread you detach (if you use objects inside them, of course), and possibly runloops too.
     
   
 
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Top
Privacy Policy
All times are GMT -4. The time now is 01:46 PM.
All contents of these forums © 1995-2017 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.8 © 2000-2017, Jelsoft Enterprises Ltd.,