Archive for September 24th, 2010

24
Sep

The Great Dealloc Debate

Must have been a slow week for everyone else on the Cocoa programming front; the tempest in a teapot du jour is, wait for it … the proper etiquette for dealing with your releasable instance variables in -dealloc. Yes, really. Everybody agrees that using mutators is a bad idea, because it triggers KVO observers at a remarkably inopportune time would be the most obviously compelling reason. After that … opinions vary. Wildly.

A good point to pick up the debate is Jeff Lamarche’s Dealloc which lines up the options of setting to nil or not, and then Daniel Jalkut goes off in Don’t Coddle Your Code about how apps should crash if something’s wrong not hide it, and then Messr. Lamarche follows up with More on dealloc providing another pattern for super-defensive multithreading, and blahblahblah. One of the more interesting blahblahblah’s is digdog’s To nil, or not to nil, that is the question where he builds an interesting case for niling which turns out to be based on a compiler bug about not allowing access to synthesized ivars. Which you should realize is a bug not a design, if you don’t like we didn’t.

Personally, we come completely down on the side that software you put in the App Store should NEVER crash if POSSIBLY avoidable, because you can’t distribute a fix without a submission cycle! And niling out will avoid almost all crashes. So you should do that. If as in Messr. Jalkut’s ludicrously contrived example the effect of [receiver method] being called when receiver is nil is the wrong thing, well then test that receiver exists before calling it. We pretty much tend to follow a pattern that does that anyway whenever there’s a momentous decision at stake through leftover C++ habits, so that doesn’t strike us as ineffably wrongheaded as some more Cocoaheaded purist might find it.

However, we also come completely down on the side of finding whatever bugs you can before release. That’s not actually an argument for leaving the pointers dangling as most recommend; we’ve seen too many completely wacky behaviours in completely unrelated object YYY being caused by a dangling pointer in deallocated object XXX wasting more time to track down than the behaviour of a niled instance would have been noticed to think that seriously is all that good an idea.

No, what you really want is something like NSZombieEnabled without the overhead for your development cycles, and as non-crashing as possible in something the user gets through the App Store. So we vote for something along what Kevin Ballard provided as the very first comment to the “Dealloc” post [UPDATE: Now edited to compile correctly]:

#if DEBUG
#define MCRelease(x) do { [x release]; if (!getenv("NSZombieEnabled")) x = (id)0xDEADBEEF; } while (0)
#else
#define MCRelease(x) [x release], x = nil
#endif

Yes. Yes, that would be the One True And Correct Way™ to handle releasing your variables in -dealloc, wethinks; and the entire rest of the ongoing debate is just a waste of time. But if there’s some actual problem with that strategy, be sure to throw your two cents worth in. At the rate this thing is going, we’ll be able to retire the national debt in no time…