More specific, general Objective-C memory management
Everything I've read about objective-c memory management makes it incredibly simple. To paraphrase everyone: "release whatever you select, save or copy." But I think there are a few more specific cases that are not so clear. Below are examples of situations. What's the right procedure for everyone:
SITUATION No. 1:
Foo *foo = [[foo alloc] init];
Foo *fooToo = [[[foo alloc] init] autorelease];
foo = fooToo;
does foo need to be freed before assigning it to fooToo?
SITUATION # 2 I seem to have a lot of glitches when I do things like: (.h and .m for convenience).
Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;
-(id)init{
self = [super init];
}
-(void)dealloc{
[super dealloc];
[foo release];
}
I am constantly told: "Always release in dealloc what you set the save property". But it will fail if done as I showed.
SITUATION # 3 A similar situation that will also crash: (.h and .m for convenience).
Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;
-(id)init{
self = [super init];
self.foo = nil;
}
-(void)dealloc{
[super dealloc];
[foo release];
}
for some reason, when my code does this before dealloc, foo is not == nil.
SITUATION # 4 Finally, just a question of what general thinking process people use when choosing between
self.foo = bar;
and
foo = bar;
when is foo declared the same as in the above cases? Is self.foo
just another way of coding:
foo = [bar retain]
;
source to share
Situation number 1:
Yes, you need to free foo
it before you lose the link to it. Given that you singled it out, you are responsible for freeing it. If you reassigned foo
before its release, you will no longer be able to release it!
Situation number 2:
Correct implementation dealloc
:
- (void)dealloc {
[foo release];
[super dealloc];
}
The method dealloc
must call the super method dealloc
, not the method release
. Also, you need to release the fields first before calling[super dealloc]
Situation # 3: Same as Situation # 2.
Situation number 4:
I always prefer to use self.foo = bar
as it does the following steps when needed:
- liberation
foo
- preservation
bar
- appropriation
foo
bar
Assigns foo = bar
and foo = [bar retain]
does not release the previous object foo
.
source to share
Wait. Stop. Msaeed's answer is correct, in turn, but fails to highlight the real problem.
Either you don't think like a computer, or you use too much magic for every line of code.
Please don't take this as an insult to make a very light mistake and do what every programmer does when new in the environment (I've made some really fantastic magic assumptions since Objective-C in 1989).
Review the situation.
SITUATION # 1: ... delete unnecessary code ...
foo = fooToo;
This is a simple assignment. Regardless of foo
what was contained before, the object reference in your case will now be overwritten by the value fooToo
. There is no magic. There is no additional execution of the method or lines of code.
If foo
contains a reference to a saved pior object to that line of code. The link will be overwritten. If you need release
foo
to do so before rewriting the link, but it's orthogonal to the assignment.
SITUATION # 2: ... delete unnecessary code ...
-(void)dealloc{
[super dealloc];
[foo release];
}
Computer playback; you ask super dealloc and then assume the instance variable is valid after the super has been deallocated. Bad news. Boom.
There is no magic here. foo
is a reference via self of an instance variable. -dealloc
destroys self and therefore foo
has no effect anymore.
(I believe the static analyzer will catch this. If not, it should.)
SITUATION No. 3:
See # 2. This is the same problem. You are accessing an instance variable of an instance that is no longer valid.
SITUATION No. 4:
self.foo = bar;
The same as:
`[self setFoo: bar];
(Banning any setter = shenanigans)
So the key difference is what the implementation - handwritten or @synthesized - of -setFoo: does. In your case, this is retain
bar. What is different from foo = bar;
what is not saved; it's just the destination of the link to bar
.
I highly recommend that you review the introductory Objective-C documentation. This will help. However, I also encourage you to step back and really think through what exactly each line of code does in the situations above. There is no magic and the actual behavior is very simple.
source to share