views:

61

answers:

2
#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER release]; __POINTER = nil; }

Why is does three20 consider it safe to assign an ivar to nil after releasing it? Is it unsafe to leave out the ivar = nil step?

This is all I found: http://github.com/facebook/three20/commit/1b946f475fb28d60e0aafc9ef394050c642c3a5b#commitcomment-115517

I don't think I'm using KVO/KVC, but I'm not really sure. I'm reading up on it now.

Thanks!

Matt

+1  A: 

In particular for the case of releasing ivars in dealloc there is a fair amount of debate in the community about whether it is better to set them to nil after releasing or not.

The pro-nil camp feel that in general it makes the app less likely to crash in the unfortunate case where an object is accessed after being deallocated, or even during in the case of multi-threaded applications.

The anti-nil camp doesn't feel like the above argument is particularly useful because they feel the app SHOULD crash in such a case to make it that much more obvious that your application has a defect (it is accessing a deallocated object).

That's not necessarily the most comprehensive summary of the positions, but it gives you an idea of the "controversy" involved.

The KVO/KVC issue is somewhat separate as that is an argument not about whether to set the ivar to nil, but whether it's safe to use the setter of a property to do so because of possible side-effect issues (like KVO/KVC).

imaginaryboy
Thanks. That makes sense. What do you think about Yuji's third option?
MattDiPasquale
+2  A: 

When inside -dealloc, this question splits the Objective-C gurus. read this recent blog entry for example.

When inside an implementation of other methods, my personal opinion is that you shouldn't keep the variable in scope after the release in the first place. This code

   SomeClass* someObject= ...
   ... use someObject ...
   [someObject release]; 
   ... more code ...

might accidentally access someObject later in code, thus leading to a crash. So you might say

   SomeClass* someObject= ...
   ... use someObject ...
   [someObject release];
   someObject=nil; 
   ... more code ...

would be better, because messaging to nil is harmless. However, in this case you can remove the danger altogether:

   {
      SomeClass* someObject= ...
      ... use someObject ...
     [someObject release]; 
   }
   ... more code ...

Here I'm using a {...} block to limit a scope of a variable. Then the use of someObject later is simply a compile-time error.

Yuji
I like the third option. I didn't know you could do that. But, I've never seen that before. If it's the best way to do it, then why don't I ever see it. Should I start doing that? Does it make the code messy?
MattDiPasquale
I read the blog entry that you linked to. The macro option they give seems like a good solution.
MattDiPasquale
Yeah, scoping the variable in the middle of a method can be a good idea and I've done it as well. I tend to be lazy about it though because I have yet to ever be bitten by this.
imaginaryboy
I think the reason why we don't see it very often is that it's not widely realized that you can have `{...}` block not associated to `if`, `while` etc or function/method definitions. But it has been possible to use such a `{...}` block and introduce new stack variables since the old ANSI C at least. That was quite convenient back then, when you couldn't define a stack variable in a middle of a function... See Sec. 3.6 of the old standard linked from the Wikipedia article: http://en.wikipedia.org/wiki/C_(programming_language)
Yuji
The reasoning given in the blog post is erroneous. The argument seems to be that other threads can access deallocated ivars of an object being deallocated. If they are set to nil, the access is harmless. Unfortunately, setting them to nil is no good after they have been deallocated because `[obj dealloc]; obj = nil;` is not atomic. It's far better to use atomic properties so that objects can't be released while threads think they have ownership of them.
JeremyP