iPhone - dealloc - Release vs. nil
Asked Answered
M

5

24

Wondering if someone with experience could possibly explain this a bit more. I have seen examples of...

  [view release];

  view = nil;  

....inside the (void) dealloc.

What is the difference and is one better then the other? What is the best way?

When doing retainCount testing I have personally seen nil drop a count from 3 to 0 for me, but release only drops it from 3 to 2.

Morey answered 22/9, 2009 at 5:2 Comment(0)
C
36

What you have seen is probably these:

1) [foo release];
2) self.bar = nil;
3) baz = nil;
  1. Is releasing the object, accessing it through the instance variable foo. The instance variable will become a dangling pointer. This is the preferred method in dealloc.

  2. Is assigning nil to a property bar on self, that will in practice release whatever the property is currently retaining. Do this if you have a custom setter for the property, that is supposed to cleanup more than just the instance variable backing the property.

  3. Will overwrite the pointer baz referencing the object with nil, but not release the object. The result is a memory leak. Never do this.

Cherenkov answered 22/9, 2009 at 5:12 Comment(6)
so using number 3 inside the viewDidLoad will not release the memory of an alloc object?Morey
Nope, it using 3) will never release memory, unless you are in a garbage collected obj-C on Mac OS X.Cherenkov
Doing self.bar = nil can also cause a memory leak. If the property is defined as @retain, it will just work as expected; if you define it as @copy then you have a memory leak.Lawgiver
@AlBlue: No it will not result in a memory leak. Using retain, or copy will have the same semantic os releasing the previous object referenced by the property. The only difference is how a new value is acquired; ´ivar = [newValue retain];` vs. ivar = [newValue copy]. Both will release the old value with a simple [ivar release].Cherenkov
Let me please verify: "self.property = foo" goes through the synthesized setter (releasing the old value, retaining the new value), but "property = foo" just slams in a new pointer to the property field, bypassing the setter?Chao
Using 2) can be dangerous, which is why 1) is preferred. If the setter is overridden by a subclass, a method is now being invoked in the subclass whose dealloc method has already been invoked. The general rules for safe properties/ivar access is: 1) Use the ivar directly from within init, dealloc and setters/getters. 2) All other access should go via the property.Ramose
P
8

If you are not using properties (where self.property = nil will also release an object) then you should ALWAYS follow a release by code that sets the reference to nil, as you outlined:

[view release]; view = nil;

The reason is that it avoids he possibility that a reference can be used that is invalid. It's rare and hard to have happen, but it can occur.

This is even more important in viewDidUnload, if you are freeing IBOutlets - that's a more realistic scenario where a reference might go bad because of memory warnings unloading a view, and then some other code in the view trying to make use of a reference before the view is reloaded.

Basically it's just good practice and it will save you a crash at some point if you make it a habit to do this.

Pinta answered 22/9, 2009 at 16:57 Comment(4)
so essentially for ivars with properties, we can do this? - (void)dealloc { self.iVar = nil }Omnibus
You can, although you were in the past told to not use the setters in dealloc lest there be side effects... but now that internal class vars can get created automatically where you have to use the setters, I guess it's considered OK to use that method to set variables to nil in dealloc.Pinta
You can still reference synthesised instance variables, you do not have to use the setter in dealloc.Oraleeoralia
A great point, in fact you should not use the setter in dealloc.Pinta
O
2

@bbullis22 you have seen the restain count drop from 3 to 0 because you set the reference to nil. then you asked for the retaincount of 'nil' which is zero. however, the object that used to be referenced has the same retain count - 1 (due to setting the reference to nil). using release, the reference still references the same object, so that's why you see the retain count drop from 3 to 2 in this situation.

Optimist answered 3/3, 2010 at 12:23 Comment(0)
H
1

As far as usage inside your code, in your dealloc you don't need the assignment to the property, releasing is all you need to do.

- (void)dealloc {
    [myProperty release]; // don't need to assign since you won't have the object soon anyway
    [super dealloc];
}
Hanover answered 22/9, 2009 at 5:57 Comment(1)
Wait, shouldn't that last line be [super dealloc] ?Alek
W
0

I think using both is kind of safety net. With only release in place you could run in problem if you screwed reference counting management. You would release an object, giving its memory back to system but pointer would be still valid.

With nil you are guaranteed that program will not crash since sending message to nil does nothing.

Whit answered 22/9, 2009 at 5:12 Comment(2)
You recommend calling both? Nil before release or vise versa?Morey
Assigning nil before release means you are sending release to nil (thus not freeing the object). Assigning to nil is optional (as the object is being deallocated, the instance variable shouldn't ever be referenced again)Archive

© 2022 - 2024 — McMap. All rights reserved.