I'm just starting iphone development and am getting my head around objective-C, the framework, etc.. Why does all sample code follow the following pattern:
I'm just starting iphone development and am getting my head around objective-C, the framework, etc.. Why does all sample code follow the following pattern:
The second version is a memory leak. You alloc/init the object, which gives you a retained copy, and then you assign it somewhere else without releasing it. You could do it in one line with an autorelease but in general it's better to do an explicit release as soon as you're done with something. If the object could be released immediately but you've put autorelease on it, the object will stick around until the next time the autorelease pool drains. Probably not a big deal most of the time, but the iPhone is very tight on memory so why not squeeze every last little drop of space out of it?
The second version is a memory leak. You alloc/init the object, which gives you a retained copy, and then you assign it somewhere else without releasing it. You could do it in one line with an autorelease but in general it's better to do an explicit release as soon as you're done with something. If the object could be released immediately but you've put autorelease on it, the object will stick around until the next time the autorelease pool drains. Probably not a big deal most of the time, but the iPhone is very tight on memory so why not squeeze every last little drop of space out of it?
Hmm, the subtleties of memory management in objective-c. In the first case, when the assignment is done, the property will (likely) have a retain directive, so the count goes up to 2, but then when we release it, it goes back down to 1 (only for the property), and eventually goes to 0 in the dealloc, I imagine. Is this correct?
What would happen in the second case? Would it get a retain count of 2 upon assignment, then get stuck with a count of 1 afterward the dealloc?
Hmm, the subtleties of memory management in objective-c. In the first case, when the assignment is done, the property will (likely) have a retain directive, so the count goes up to 2, but then when we release it, it goes back down to 1 (only for the property), and eventually goes to 0 in the dealloc, I imagine. Is this correct?
What would happen in the second case? Would it get a retain count of 2 upon assignment, then get stuck with a count of 1 afterward the dealloc?
No he doesn't. Back to Cocoa memory management school for both of you!
Quote:
Hmm, the subtleties of memory management in objective-c. In the first case, when the assignment is done, the property will (likely) have a retain directive, so the count goes up to 2, but then when we release it, it goes back down to 1 (only for the property), and eventually goes to 0 in the dealloc, I imagine. Is this correct?
What would happen in the second case? Would it get a retain count of 2 upon assignment, then get stuck with a count of 1 afterward the dealloc?
Forget about the property and whether or not it retains for a minute. The goal of Cocoa memory management is to balance your retains and releases. Alloc gives you an object with a retain count of 1 so it is up to YOU to release (or autorelease) it. Since you didn't do that, it doesn't matter whether or not the property retains it - you still have a count of 1 that has to be dealt with.
The retain count won't go to 0 in the dealloc - retain counts are never automatically decremented like that. The only time the retain count goes down is when you do a release or autorelease. In fact, dealloc is not even called until the retain count of the object hits zero.
I know it's a little confusing at first but you will get the hang of it. Just stick with it and don't get discouraged. I certainly made my fair share of mistakes!
No he doesn't. Back to Cocoa memory management school for both of you!
Forget about the property and whether or not it retains for a minute. The goal of Cocoa memory management is to balance your retains and releases. Alloc gives you an object with a retain count of 1 so it is up to YOU to release (or autorelease) it. Since you didn't do that, it doesn't matter whether or not the property retains it - you still have a count of 1 that has to be dealt with.
The retain count won't go to 0 in the dealloc - retain counts are never automatically decremented like that. The only time the retain count goes down is when you do a release or autorelease. In fact, dealloc is not even called until the retain count of the object hits zero.
I know it's a little confusing at first but you will get the hang of it. Just stick with it and don't get discouraged. I certainly made my fair share of mistakes!
+1
Done right, there is minimal dependency between classes and methods for the correct memory behaviour.
retains and releases should be balanced within the method (or class in the case of instance variables).
Just imagine someone else is writing all the other methods in your project, and you have zero contact with this person, how do you ensure correct memory management? If each person follows the rules, they don't need to communicate where they are doing retains/releases, and correct memory management ensues. This is how the Cocoa framework is written.
+1
Done right, there is minimal dependency between classes and methods for the correct memory behaviour.
retains and releases should be balanced within the method (or class in the case of instance variables).
Just imagine someone else is writing all the other methods in your project, and you have zero contact with this person, how do you ensure correct memory management? If each person follows the rules, they don't need to communicate where they are doing retains/releases, and correct memory management ensues. This is how the Cocoa framework is written.
I should have been more precise in my original response. What I meant is that in an object dealloc, one typically releases one's properties. But what you both indicate makes better sense - it's actually irrelevant. Any individual method needs to track its own allocations and release them. That's probably the best way to think about it.
I thought autorelease marked the item for garbage collection at the later time, and GC is not available on the iphone.
I'm coming from programming ruby the last couple of years - life used to be so easy....
I thought autorelease marked the item for garbage collection at the later time, and GC is not available on the iphone.
not quite. autorelease just marks an object for a release action "at some point in the future." the future point is typically the next time the run loop is entered, which is usually pretty quick. (i'm qualifying this heavily with words like "typically" and "usually" because you can do things to interfere with this, but most of the time you won't.)
garbage collection, the way most people think of it, is completely automatic and happens outside the control of the programmer. autorelease is under your control.
my advice would be to only use autorelease when you are returning an object that you alloced. eg:
As you can see here, you've alloced the object, so it is your responsibility to provide a balancing release message. However, you want to return it to another method, so you can't just release it, or it would be lost before the other method got it. Autorelease is your friend in this case.
Quote:
I'm coming from programming ruby the last couple of years - life used to be so easy....
tell me about it - i was doing perl and php for the last 10 years. cocoa was quite a kick in the pants, took me about 6-8 weeks to get comfortable with it.
What would happen in the second case? Would it get a retain count of 2 upon assignment, then get stuck with a count of 1 afterward the dealloc?
Quote:
Originally Posted by RLScott
You've got it exactly right!
Quote:
Originally Posted by jsd
No he doesn't. Back to Cocoa memory management school for both of you!
Hmm... I believe the "second case" is the one quoted below, so unless I'm missing something, I think the "you've got it exactly right" assessment is indeed correct.
Hmm... I believe the "second case" is the one quoted below, so unless I'm missing something, I think the "you've got it exactly right" assessment is indeed correct.
Well, it does have an extra retain on it, but it also would never get to dealloc with a retain count of 1.
Hmm... I believe the "second case" is the one quoted below, so unless I'm missing something, I think the "you've got it exactly right" assessment is indeed correct.
The line of code you quoted generates an object with a retain count of 1. It *might* have a retain count of 2 after being assigned to self.navigationController - but you don't know that. You're not supposed to know, or even need to know. The original poster said it generated a retain count of 2, which is possibly wrong (the assignment might not do a retain at all, or it might assign it to other things, leading to a count of more than 2, who knows what setNavigationController is doing - again, irrelevant). The important principle to take away is that you shouldn't think about what anybody else is doing with your stuff. You need to balance your own retains and releases, and in this case, they aren't.
Well, it does have an extra retain on it, but it also would never get to dealloc with a retain count of 1.
Ah... I read "...get stuck with a count of 1..." and my mind stopped reading. Right, having a retain count of 1 (or greater) "after the dealloc" makes no sense, as the dealloc will not be called until the release method drops the retain count to 0.
No he doesn't. Back to Cocoa memory management school for both of you!
None of your subsequent explanation contradicts anything farhadf said. He did have it right, as his subsequent clarifications shows. I understood what object he was referring to when he said "eventually goes to zero in the dealloc", and that he as not assuming the release was automatic, but was part of the usual explicit releases that a programmer does in a dealloc method.