Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 06-04-2009, 01:28 PM   #1 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 87
Default To autorelease or not to autorelease

I was reading a code example from a book when I found this:

Code:
	
[self.navigationItem setRightBarButtonItem:[[[UIBarButtonItem alloc]
	initWithTitle:@"Randomize"
	style:UIBarButtonItemStylePlain
	target:self
	action:@selector(randomizePositions)] autorelease]];
If I do a refcount or retainCount for self.navigationItem.rightBarButtonItem it shows that it has 3 references!
Why? Should I care?
Why do I have to write autorelease there?
What if I don't?
When do I know I should call autorelease?

Best regards,
Matias

Last edited by MatuX; 06-04-2009 at 01:34 PM.
MatuX is offline   Reply With Quote
Old 06-04-2009, 02:07 PM   #2 (permalink)
New Member
 
Join Date: Jun 2009
Posts: 11
Default

Quote:
Why?
By using autorelease, you are making the object to be placed ion autorelease pool.

Quote:
Should I care?
Yes, if you are not doing memory management on your own and
NO, if you are doing memory management on your own.

Quote:
Why do I have to write autorelease there?
No compulsion to write. Please refer the above two questions.

Quote:
What if I don't?
Please refer the above questions.

Quote:
When do I know I should call autorelease?
It depends on you. Please refer the above questions.
inflecsys is offline   Reply With Quote
Old 06-04-2009, 02:15 PM   #3 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 87
Default

Quote:
Originally Posted by inflecsys View Post
By using autorelease, you are making the object to be placed ion autorelease pool.



Yes, if you are not doing memory management on your own and
NO, if you are doing memory management on your own.



No compulsion to write. Please refer the above two questions.



Please refer the above questions.



It depends on you. Please refer the above questions.
You put it in so simple terms but I'm really confused about the fact that while I'm allocating one single object and giving it away, it should(?) have just one reference, but it has 3.
How am I sure that if I don't write autorelease it will get released by the object who owns it?
Because the fact that the original had an "autorelease" makes me doubt of the fact that, while I can be perfectly fine managing my own memory, the API still needs that I make a call to autorelease every now and then.

I mean, to me and my code, putting an autorelease there is exactly the same. I don't own the object, the API does, the API should release it.
Is it exactly the same for the API?
Will it make the appropriate release calls?
MatuX is offline   Reply With Quote
Old 06-04-2009, 02:57 PM   #4 (permalink)
Senior Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
Default

Code:
	
[self.navigationItem setRightBarButtonItem:[[[UIBarButtonItem alloc]
	initWithTitle:@"Randomize"
	style:UIBarButtonItemStylePlain
	target:self
	action:@selector(randomizePositions)] autorelease]];
In this case, yes, I believe you should autorelease. You called alloc/init on the object, so you need to release it somewhere. The easiest way to do that is to call autorelease, so that it gets released at the end of the current event.

Don't worry about who else retained it, and why - that's their business.
Here's another, also correct, way to do what you're doing:

Code:
UIBarButtonItem *newItem = [[UIBarButtonItem alloc]
	initWithTitle:@"Randomize"
	style:UIBarButtonItemStylePlain
	target:self
	action:@selector(randomizePositions)];

[self.navigationItem setRightBarButtonItem: newItem];

[newItem release];
This doc was very helpful to me:
Very simple rules for memory management in Cocoa
__________________

Free Games!
smasher is offline   Reply With Quote
Old 06-04-2009, 03:33 PM   #5 (permalink)
jsd
at this moment
 
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 900
Default

Quote:
Originally Posted by MatuX View Post
If I do a refcount or retainCount for self.navigationItem.rightBarButtonItem it shows that it has 3 references!
Why? Should I care?
In general, you should not look at object retainCounts... They are often misleading. If you are using any framework classes, they will have retains all over your stuff (as you discovered). Don't worry about it. Remember, the goal isn't to make sure the retainCount is zero - the goal is to make sure all your retains & releases are balanced. myfoo = [[foo alloc] init] does an implicit retain, so it must be balanced with a release or autorelease.

I used to use autorelease all the time because I didn't really understand what I was doing, but I'm trying to break the habit and use it only when absolutely necessary. You should prefer the method that Smasher mentioned. Alloc/init, then use the object or assign it somewhere else, then release. Clean and simple, immediately obvious that the retains & releases are balanced.

If you have any doubts about your code, I recommend investigating the Clang Static Analyzer. It runs over your code and can identify problematic memory management areas for you in a way that the normal compiler and even the Leaks tool can't.
jsd is offline   Reply With Quote
Old 06-04-2009, 08:42 PM   #6 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 87
Default

Thanks a lot for all of your responses!

Common sense dictated to me that since I wasn't retaining the object I just allocated (and I was giving it directly to another object), the retain count wouldn't increase.

Does this means that if I do [obj setSomething:[[OtherObj alloc] init]; it will automatically become a leak? If it is so, why the compiler doesn't signal a warning here?

So the rule is that every time I do "alloc", the retain count increases 1 and I am the one responsible to decrease it?

Edit:
If that is the rule, isn't there a way to stop the language from doing this? It will make the code really messy if I can't do something like:

Code:
[myObj setThis:[[OtherObj alloc] init];
and I'm forced to add these redundant lines:

Code:
OtherObj otherObj = [[OtherObj alloc] init];
[myObj setThis:otherObj];
[otherObj release];
------

And what if the property is set to assign instead of retain? When I do "release" I will render the allocated memory unusable?
Must I check for every property if its set to assign or retain every time I use it?

Last edited by MatuX; 06-04-2009 at 08:58 PM.
MatuX is offline   Reply With Quote
Old 06-04-2009, 10:10 PM   #7 (permalink)
Former NeXTStep Developer
 
Join Date: Mar 2009
Posts: 997
Default

Quote:
Originally Posted by MatuX View Post
Thanks a lot for all of your responses!

Common sense dictated to me that since I wasn't retaining the object I just allocated (and I was giving it directly to another object), the retain count wouldn't increase.

Does this means that if I do [obj setSomething:[[OtherObj alloc] init]; it will automatically become a leak? If it is so, why the compiler doesn't signal a warning here?

So the rule is that every time I do "alloc", the retain count increases 1 and I am the one responsible to decrease it?

Edit:
If that is the rule, isn't there a way to stop the language from doing this? It will make the code really messy if I can't do something like:

Code:
[myObj setThis:[[OtherObj alloc] init];
and I'm forced to add these redundant lines:

Code:
OtherObj otherObj = [[OtherObj alloc] init];
[myObj setThis:otherObj];
[otherObj release];
------

And what if the property is set to assign instead of retain? When I do "release" I will render the allocated memory unusable?
Must I check for every property if its set to assign or retain every time I use it?
That's what autorelease is for:

Code:
[myObj setThis:[[[OtherObj alloc] init] autorelease];
You created it, you're making sure it gets released. AFTER the other object has a chance to retain it if needed. Just make sure that myObj DOES retain it if needed.

Also, the compiler can't give a warning because it doesn't know what [myObj setThis:] is going to do.

joe
FlyingDiver is offline   Reply With Quote
Old 06-05-2009, 12:47 PM   #8 (permalink)
jsd
at this moment
 
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 900
Default

Quote:
Originally Posted by MatuX View Post
And what if the property is set to assign instead of retain? When I do "release" I will render the allocated memory unusable?
Must I check for every property if its set to assign or retain every time I use it?
Nope. That's not your job. Your job is to balance your own retains and releases. (Of course, if you wrote the class that's getting the property, you're responsible for making it sure it works correctly.)

Release does not necessarily deallocate the object - only if its retain count drops to zero.

If you alloc an object, then assign it to a property of another class, you can go ahead and release it when you're done with it. It's up to the other class to have retained it (if it needs to). You shouldn't worry about it. Remember, as long as there's at least one retain on it, the object will not go away.

If you're worried about premature releases, check out the NSZombieEnabled flag. FCS Blog NSZombieEnabled for the debugger adverse
jsd is offline   Reply With Quote
Old 06-05-2009, 02:48 PM   #9 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 87
Default

Thanks a lot for all your answers, they are helping me a lot for sure!!!

On another note, I'm reading about the Autorelease pool. Did I understand this correctly?
Code:
-(void)myFunc
{
 NSAutoreleasePool * myOwnPool = [[NSAutoreleasePool alloc] init];
 Obj o1 = [[Obj alloc] init];
 Obj o2 = [[Obj alloc] init]; 
 Obj o3 = [[Obj alloc] init];

 [whateverOtherObject setObj:o1]; //obj/setObj property set to retain
 [whateverObject setObj:o2 andObj:o3]; //obj/setObj property set to retain

 [myOwnPool release];
}
Would this automatically release o1, o2, o3 and still keep the memory allocated for "whateverOtherObject" and "whateverObject"?

Thanks!
MatuX is offline   Reply With Quote
Old 06-05-2009, 02:59 PM   #10 (permalink)
Former NeXTStep Developer
 
Join Date: Mar 2009
Posts: 997
Default

Quote:
Originally Posted by MatuX View Post
Thanks a lot for all your answers, they are helping me a lot for sure!!!

On another note, I'm reading about the Autorelease pool. Did I understand this correctly?
Code:
-(void)myFunc
{
 NSAutoreleasePool * myOwnPool = [[NSAutoreleasePool alloc] init];
 Obj o1 = [[Obj alloc] init];
 Obj o2 = [[Obj alloc] init]; 
 Obj o3 = [[Obj alloc] init];

 [whateverOtherObject setObj:o1]; //obj/setObj property set to retain
 [whateverObject setObj:o2 andObj:o3]; //obj/setObj property set to retain

 [myOwnPool release];
}
Would this automatically release o1, o2, o3 and still keep the memory allocated for "whateverOtherObject" and "whateverObject"?

Thanks!
No, because none of those objects were marked for autorelease. If you had done:

Code:
-(void)myFunc
{
 NSAutoreleasePool * myOwnPool = [[NSAutoreleasePool alloc] init];
 Obj o1 = [[[Obj alloc] init] autorelease];
 Obj o2 = [[[Obj alloc] init] autorelease]; 
 Obj o3 = [[[Obj alloc] init] autorelease];

 [whateverOtherObject setObj:o1]; //obj/setObj property set to retain
 [whateverObject setObj:o2 andObj:o3]; //obj/setObj property set to retain

 [myOwnPool release];
}
Then the only retains would be by whateverObject, and when it releases o1, o2, and o3, they would get deallocated.

joe
FlyingDiver is offline   Reply With Quote
Old 06-05-2009, 03:04 PM   #11 (permalink)
jsd
at this moment
 
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 900
Default

Since you never sent any of those objects an autorelease message, they will NOT be released when the pool drains. You leaked all three objects.

You should use [myOwnPool drain] btw unless you know for sure you will never reuse any of that code in Mac OS with garbage collection. On iPhone, release & drain are equivalent though... for now anyway.
jsd is offline   Reply With Quote
Old 06-05-2009, 03:54 PM   #12 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 87
Default

Thank you a lot JSD and FlyingDiver!

I think I can handle it from here... Will surely post new threads if anything above my understanding happens.

Thanks a lot everyone, you've been of great help!
MatuX is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting 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
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Stats
Members: 158,471
Threads: 89,089
Posts: 380,121
Top Poster: BrianSlick (7,091)
Welcome to our newest member, cherubic
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 03:52 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0