 |
 |
|
 |
06-04-2009, 12:28 PM
|
#1 (permalink)
|
|
Registered Member
Join Date: May 2009
Posts: 57
|
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 12:34 PM.
|
|
|
06-04-2009, 01:07 PM
|
#2 (permalink)
|
|
New Member
Join Date: Jun 2009
Posts: 11
|
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.
Quote:
|
Why do I have to write autorelease there?
|
No compulsion to write. Please refer the above two questions.
Please refer the above questions.
Quote:
|
When do I know I should call autorelease?
|
It depends on you. Please refer the above questions.
|
|
|
06-04-2009, 01:15 PM
|
#3 (permalink)
|
|
Registered Member
Join Date: May 2009
Posts: 57
|
Quote:
Originally Posted by inflecsys
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?
|
|
|
06-04-2009, 01:57 PM
|
#4 (permalink)
|
|
Senior Member
iPhone Dev SDK Supporter
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 2,573
|
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
__________________
|
|
|
06-04-2009, 02:33 PM
|
#5 (permalink)
|
|
at this moment
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 870
|
Quote:
Originally Posted by MatuX
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.
|
|
|
06-04-2009, 07:42 PM
|
#6 (permalink)
|
|
Registered Member
Join Date: May 2009
Posts: 57
|
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 07:58 PM.
|
|
|
06-04-2009, 09:10 PM
|
#7 (permalink)
|
|
Former NeXTStep Developer
Join Date: Mar 2009
Posts: 997
|
Quote:
Originally Posted by MatuX
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
|
|
|
06-05-2009, 11:47 AM
|
#8 (permalink)
|
|
at this moment
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 870
|
Quote:
Originally Posted by MatuX
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
|
|
|
06-05-2009, 01:48 PM
|
#9 (permalink)
|
|
Registered Member
Join Date: May 2009
Posts: 57
|
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!
|
|
|
06-05-2009, 01:59 PM
|
#10 (permalink)
|
|
Former NeXTStep Developer
Join Date: Mar 2009
Posts: 997
|
Quote:
Originally Posted by MatuX
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
|
|
|
06-05-2009, 02:04 PM
|
#11 (permalink)
|
|
at this moment
Join Date: Mar 2009
Location: San Francisco, CA
Posts: 870
|
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.
|
|
|
06-05-2009, 02:54 PM
|
#12 (permalink)
|
|
Registered Member
Join Date: May 2009
Posts: 57
|
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!
|
|
|
 |
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
» Advertisements |
» Online Users: 386 |
| 45 members and 341 guests |
| activ8, alex_ivanov, benoitr007, Blitfast, bobvanratingen, CAmaninacan, ColouredRobot, cye, dave1619, Dorald, fbronner, flamingliquid, icordoba, ImpresionesWeb, javaconvert, jbourne08, Jeremy1026, Jupiterus, Kalimba, kbegemandev, kkrizka, KSA_girl, linkmx, mikeyb, MiniRobinho, miv, mixer555, MrMattMac, Noise, Notable, orange gold, psilocybin, quky, richyclements, ricobeck, robmonty, Rudy, scalar, scotopia, shan, sourman, StefanL, teras, That Don Guy |
| Most users ever online was 779, 05-11-2009 at 09:55 AM. |
» Stats |
Members: 24,257
Threads: 39,039
Posts: 171,222
Top Poster: smasher (2,573)
|
| Welcome to our newest member, arielgren |
|