I have a pretty basic question. In some examples I've seen, objects are just released in the dealloc method. In others, the objects are released and then set to nil
. Is there a reason for this? Is setting to nil after releasing advantageous?
1. Just release
- (void)dealloc {
[airplane release];
[super dealloc];
}
Now the object reference points to a random position, which may be one of two things:
The effect of a further method calls through this pointer is one of these three (which one is undefined):
EXC_BAD_ACCESS
because the pointer points to garbage.2. Release and nil
- (void)dealloc {
[airplane release], airplane = nil;
[super dealloc];
}
Now the object reference is nil and any further method calls are ignored. This may silently cause a defined but unforeseen lateral effect in your code, but at least it doesn't crash your application.
3. Nil and release
- (void)dealloc {
id temp = airplane;
airplane = nil;
[temp release];
[super dealloc];
}
This is the same as before, but it removes that small window between release and nil where the object reference points to an invalid object.
It is a matter of choice:
NSZombieEnabled=TRUE
then just release, don't nil the zombie!A easy way to defer your choice is using a macro. Instead [airplane release]
you write safeRelease(x)
where safeRelease is the following macro that you add to your .pch target file:
#ifdef DEBUG
#define safeRelease(x) [x release]
#else
#define safeRelease(x) [x release], x=nil
#endif
This macro doesn't respect zombies. Here is the problem: when NSZombieEnabled
is TRUE
the object turns into a NSZombie
. If you nil its object reference, any call sent to him will be ignored.
To fix that, here is a macro from Kevin Ballard that sets the pointer to an invalid made up reference ONLY when NSZombieEnabled
is FALSE
. This guarantees a crash during debug time if zombies are not enabled, but leaves the zombies be otherwise.
#if DEBUG
#define safeRelease(x) do { [x release]; if (!getenv("NSZombieEnabled")) x = (id)0xDEADBEEF; } while (0)
#else
#define safeRelease(x) [x release], x = nil
#endif
Apple doesn't have a recommendation on which one is best. If you want to read the thoughts of the community here are some links (the comment threads are great too):