Copyright 2004 by M. Uli Kusterer Tue, 30 Dec 1969 07:58:58 GMT Comments on article blog-defensive-coding-in-objective-c at Zathras.de http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm blog-defensive-coding-in-objective-c Comments witness_dot_of_dot_teachtext_at_gmx_dot_net (M. Uli Kusterer) witness_dot_of_dot_teachtext_at_gmx_dot_net (M. Uli Kusterer) en-us Comment 25 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment25 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment25 Uli Kusterer writes:
Peter,

>What if I go out and buy a second one and plug them both in?

That's beside the point, but for the sake of completeness: There are USB devices where having more than one on the same machine wouldn't make sense, or simply wouldn't work. Think of something that inputs uncompressed video. A USB 2.0 bus would probably be at capacity with one already. Also, the class represents a (type of) device. If you have e.g. an audio compressor, you may have one singleton representing all devices. If I plug in several, it would transparently distribute the load across all of them, maybe even GCD-like across applications.

>Why would they not use the object of the notification?

For completeness: Because, at this point, they don't know what the object is. If it's a singleton anyway, you should never get the same notification from any object but this one. So why not allow the added convenience? Yes, it's shoddy programming, but it's a fairly valid assumption, so I'd like to defend against it. Also, it's makes loose coupling possible: I can have one object that just subscribes for a notification, while another can actually cause the singleton to be created at a later time, e.g. after important setup work has been done.

Glad we worked out an agreement about setting sharedInstance in -init instead of after init returns. It's great to have a solid, full example out there at http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong
Comment 24 by Peter Hosey http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment24 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment24 Peter Hosey writes:
> By the way, could you elaborate what the benefit of mucking about with +initialize is?

Don't just look at +initialize; look at the whole implementation. It makes it practically impossible for multiple instances to exist: The only way I can think of is to send alloc, but not init, before creating the shared instance.

That does point out a bug, BTW: If you do that, then init the allocked instance after creating the shared one, init will return the allocked instance without initializing or releasing it. I've just fixed that.

The other benefit is a bit of thread-safety, as pointed out in the comments, although I wouldn't call this class “thread-safe” in general, having not tested it in any such situation.
Comment 23 by Peter Hosey http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment23 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment23 Peter Hosey writes:
“I have a singleton that represents a USB device.”

What if I go out and buy a second one and plug them both in?

There is no singleton implementation that can solve problems caused by making a singleton where it isn't appropriate. Not mine, not yours, not Apple's, not anyone's.

> Now, if someone subscribed to this notification with NIL as the object, they could already be subscribed before they call +sharedInstance. Inside of their notification handler, they call +sharedInstance to get additional information.

Why would they not use the object of the notification?
Comment 22 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment22 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment22 Uli Kusterer writes:
By the way, could you elaborate what the benefit of mucking about with +initialize is? The code would be much simpler if you just did the work in +sharedInstance and/or -init. You have to call +sharedInstance to create the object, or if you call alloc/init that's a mistake (but anyway, it would set the static sharedInstance variable). All the special ifs/thens to detect if you were called from +initialize or not seem kinda unnecessarily error-prone.
Comment 21 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment21 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment21 Uli Kusterer writes:
Peter, that's not what I'm talking about. The issue I'm thinking of is e.g.: I have a singleton that represents a USB device. In -init I register for IOKit device-plugged-in callbacks. In response to such a callback, I send an NSNotification. Trouble is, IOKit sends device-plugged-in messages right away on registration for all devices that are already plugged in.

Now, if someone subscribed to this notification with NIL as the object, they could already be subscribed before they call +sharedInstance. Inside of their notification handler, they call +sharedInstance to get additional information. With your code, that would result in endless recursion, because -init has already been called, but has not returned yet. So when the notification handler calls +sharedInstance, the sharedInstance static variable is still NIL, so +sharedInstance will alloc/init a second singleton, which will in turn register for callbacks, which will send the messages for the plugged-in devices, which will call +sharedInstance, which will alloc/init a third object...

Now this is one pathological case (a real-world example, though), but by doing the sharedInstance setting at the start of -init, you're rid of that whole class of problem. After all, the notification could be replaced with a mutator method or whatever.
Comment 20 by Peter Hosey http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment20 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment20 Peter Hosey writes:
OK, now your complaint is a bit clearer. I'm guessing that the problem case you're thinking of is somebody allocking and initing an instance without going through +sharedInstance?

Your solution is still wrong, just less wrong. If you're treating a singleton as a multipleton or regular class by allocking and initing it, you have a bug either way: You are misusing the class. The real right thing for a singleton to do would be to detect that -init's caller is not +sharedInstance and throw an exception.

Even so, consistent wrong behavior is better than inconsistent wrong behavior, so I've applied the fix you suggested to the post. Thanks. I'm not sure when I'll get around to implementing the right behavior (which would probably use backtrace(3) and dladdr); too many other things to do. Patches welcome.
Comment 19 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment19 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment19 Uli Kusterer writes:
Peter, and not doing it in init, but rather after init returns, is the problem with your sample code. It's one of the things that Apple's code does right, because it helps avoid lots of nasty bugs.
Comment 18 by Peter Hosey http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment18 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment18 Peter Hosey writes:
Yes, I'm assigning sharedInstance. No, I'm not doing it in -init.
Comment 17 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment17 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment17 Uli Kusterer writes:
Peter, in your case it's a static variable called sharedInstance, but yes, you're doing it. Well, your sample code is, anyway.
Comment 16 by Peter Hosey http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment16 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment16 Peter Hosey writes:
“… but you're doing the sSharedInstance variable assignment when -init returns…”

No, I do no such thing.
Comment 15 by Chris http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment15 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment15 I don't know how I feel about not using accessors in constructors and destructors. I think I read in the Apple doco that you should use them, because using property accessors even in constructors makes sure your objects are retained, otherwise you might forget. Besides which, it is the very fact that accessors might do other stuff which is the very reason why you probably want to use them. Yes sure, there'll be cases where this doesn't work because a method is expecting the object to be more fully constructed, then you inherit the class and get into trouble. But people inheriting from classes can *always* break the assumptions of the underlying class. The good thing in objective-c is you've got a lot of flexibility in even overriding the constructors of super-classes entirely to solve this stuff. The alternative seems to be to risk tons of bugs by trying to work around using the setters and work around doing too much in the constructor, to avoid a pretty rare case that you can deal with when it arises. If you override a setter and it is complicated and making lots of assumptions about what else is constructed, make liberal use of NSAssert to catch it quickly. Discussions of performSelector: and explicit retains in constructors and figuring out how to avoid calling stuff without repeating code, sounds like a cure worse than the disease.

Besides which, objective-c only has constructors by convention, not by a language feature. You can think of your alloced object as fully constructed as long as your code can cope with nil values anywhere. init is just a convenience multi-value setter. Of course this is extreme, but I think the problem is case by case. If you use enough asserts, then you will catch any bad assumptions of inheriting classes quickly, and they will solve their problems quickly enough.

I'm willing to be convinced otherwise, but I'm not sure about this one.
Comment 14 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment14 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment14 Uli Kusterer writes:
Not sure what point you're trying to make with regard to C not initializing to zero. But anyway, C is C, and as soon as a variable is declared, you want it to be NIL or NULL for safety's sake, because otherwise you don't notice if you forget to init something. Python may warn you, but that's really not of much help if you're stuck writing ObjC on a Mac.

Sadly, your code is just as wrong as Apple's just in other places. I agree that the retain/release/autorelease/retainCount overrides are overkill and mask bugs elsewhere, but you're doing the sSharedInstance variable assignment when -init returns, not inside -init. This means that if anything in -init causes another call to +sharedInstance, you'll enter an endless loop of creating instances of your singleton.

And if you think that can't happen, remind yourself that the main point we use singletons instead of classes with class methods is that you can subclass them, because the first instance of a singleton class or subclass "wins". A careless subclasser can easily cause such a loop by accident, even though at this point it would otherwise be perfectly safe.
Comment 13 by Peter Hosey http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment13 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment13 Peter Hosey writes:
“The problem with C is that local variables are not initialized to zero.”

Not exactly. The problem is that a variable can (and must) exist before anything has ever been put in it. Try that in Python, for example:

print x
x = 42

You'll get an exception because the variable x doesn't exist yet.

“There is a nice little example implementation of the Singleton design pattern on Apple's developer web site. Implement it.”

Better yet, don't. I have a blog post analyzing the several ways that example is wrong, and presenting a much better one: http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong
Comment 12 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment12 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment12 Uli Kusterer writes:
Jeff, the NIL chain works just fine with NSError return parameters and expressions stretched across multiple lines, as long as the message target is *always* the same variable that might be NIL. But yeah, it's still a fairly restricted set of circumstances.

As to pools: Outer pools on the stack are documented to also flush any inner pools on top of them. There is no "magic" there. Only the bottom-most pool (e.g. in a thread) might need to be specially released.
Comment 11 by Jeff http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment11 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment11 Personally I see the nil chain being useful in a very small set of real world examples. The issue with cascading a whole bunch of method calls into one line is that if one of them somewhere in the chain fails, you can't tell which.

Sure, the trivial x = [[[[myclass] alloc] init] autorelease] works ok but I don't see it in
[[[[xmanager currentx] startTransaction] openEdit] addObject:something]
because you'll nearly want those intermediate objects in a subsequent operation, and/or any of them can fail for a reason which you might need to communicate to the user in different ways. Forcing everyone to use a consistent set of Exception classes isn't workable because its not always your code in the chain, sometimes its 3rd party frameworks.

In the case where they can be chained together trivially, there should probably already be a method that does the chaining for you. Like the [[...alloc]init] pair is in [...new].

As to the issue of Objective-C vs C++, what is your stance on whether it should be your responsibility to clean up an autorelease pool if someone under you @throws - ie, should you do

NSAutoreleasePool *pool = [NSAutoreleasePool new];
@try {
... stuff ...
} @finally {
[pool drain];
}

or do you rely on the hidden (but documented) behaviour that pools seem to autorelease themselves without you asking for it? Of course, garbage collection makes this particular example moot, but on an iPhone, its an issue since you can't afford to be lazy with your memory reclamation.

Regardless of your opinion on this matter, I'm not trying to say that you should code Objective-C like C++ - but I think that the defensive measures you need to take in both are more alike than you'd think and that its better if the same mindset can be used in both cases.

I'm biased, of course, because in my day job, our (multi-million line) application uses C, C++, C#, Python and our own home-grown OO-language, all interoperating, all calling each other, etc - I need strategies that are as consistently applicable as possible.
Comment 10 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment10 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment10 Uli Kusterer writes:
Brian, I just remembered: Manually doing a retain/release means you'll have to explicitly catch exceptions if you don't want to leak on that occasion. That's another reason in favor of autorelease. Inner pools get cleaned up along with outer pools and such don't leak during an exception.
Comment 9 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment9 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment9 Uli Kusterer writes:
Jeff, fully agree that defensive coding can be overdone. Which is why I published the techniques above. These actually come from painful practical experience, and have in my experience actually improved matters.

I don't agree at all that good coding practices should always transcend languages. Compare the way ObjC and C++ deal with exceptions, and cleaning up resources when they occur. C++ recommends stack objects like smart pointers, while ObjC recommends the autorelease pool. Different libraries and languages require different mindsets. Write ObjC like C++ (or vice versa), and you'll produce bad code.

As to NIL-messaging: I like how a whole line can collapse into a no-op if one method in a chain returns NIL. It makes error handling much cleaner than ifs or try/catch, and is quite efficient as well. But I think particularly for IBOutlets, having a guaranteed crashing value would have been really good, esp. if ObjC auto-assigned that value to them.
Comment 8 by Jeff http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment8 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment8 Yes, I put the asserts into awakeFromNib - after all, its missing connections in the nib that I'm trying to protect against.

The thing about overly-defensive coding is that it tends to support "bad" practices in others. In my day job, we've had dozens of guys who say "you should always assume that the other guy does a bad job" and insist on "testing that the result is not nil, despite a successful return". The problem is that there is no rational place to stop - do you check every function that APPLE implements to make sure that it *really* returned a value, if its not documented to (occasionaly) return nil?

Of course, this all comes from that feature of Objective-C that I hate the most, that messaging nil is legal - that is the most stupid decision in the history of computing. It made some lazy programmers lives a tiny bit easier, and opened up enormous bugholes for the rest of us.

In rational languages where invoking methods against nil results in a crash which a debugger can catch, there is no argument as to whether its better or not to initialise values to nil. And I admit that my opinions are those of someone who regularly works in more than one language, and can't afford to think "if I'm working in C++, this is ok, if I'm working in Objective-C its bad". Good practices should (wherever possible) transcend mundane detail like the language you are using.
Comment 7 by Uli Kusterer http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment7 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment7 Uli Kusterer writes:
Brian, I can empathize with your sentiment. It is definitely something I've gone back and forth on, but in the end I've generally found many more leaks in code than I've found over-releases, so I'm opting for that approach for now. It is definitely a trade-off to make. Ideally, ObjC would have something like "auto-cleaning" variables, i.e. local variables that transparently do the retain/release dance like properties, then I'd head back in your direction.

Michelle, yeah, in that particular case and many others, having the controller only schedule messages on itself is better. It also doesn't violate encapsulation of objects as much. I wrote that on Twitter, but apparently forgot to put it in the article. Thanks for reminding me, I'll add it back it!

Jeff, would be curious, where do you put those asserts for IBOutlets. In -awakeFromNib? As to stopping to send notifications: Well, it's safe to e.g. do a performSelector: because it retains the target. The *real* bug here is the stale pointer. I agree, good code also cancels its notifications, but we're talking defensive coding here. This is the second line of defense after you've noticed an error has been made. Making the symbol different to the value is a neat idea, I'll have to ponder that.

Jeff J., I fully agree. You should be going through accessors wherever you can, except in those exceptional cases I'm mentioning here.

Miklos, yes, as I already explained in detail why it's bad in destructors, and I wrote that the same "applies to constructors in reverse", I thought everyone would be able to understand (like you did), that subclasses may override an accessor and expect some of their ivars to already be valid, while their constructor hasn't even run yet. And the immediate next chapter makes the point for calling other methods from the constructor.

Chris, the compiler warning is nice in theory, but as I generally develop using debug builds and debugging is infuriating with optimizations turned on, the warning doesn't really help much. I do agree though, that (especially in the case of ObjC objects) nil can mask errors. Another option would be to init them to a known garbage value like libmallocdebug does (0x55555555).
Comment 6 by Chris Suter http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment6 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment6 Chris Suter writes:
Regarding “NIL Everything That Isn't Bolted Down”: you don’t need to do what you suggest if you’ve got the appropriate compiler warning enabled, as everyone should do. The only issue with using the warning is that you only get the warnings if you’ve got optimisations turned on, i.e. it’s a Release build.
Comment 5 by Miklos Fazekas http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment5 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment5 Miklos Fazekas writes:
You don't really explain why one should avoid accessors in constructor.

The only thing is can think of is that you subclass might be overriding the accessors, and they are not prepared to run before the subclass constructor.
But this is logic holds for normal methods, so you shouldn't call any methods on self from init at all?
Comment 4 by Jeff Johnson http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment4 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment4 Jeff Johnson writes:
Good advice. The correlate to "Don't Use Accessors in Constructors or Destructors" is "Always use accessors outside constructors or destructors". In other words, don't directly access ivars or attempt to memory-manage them outside the accessors. That often leads to trouble (leaks, crashes). Just implement the accessors as -(id)myStuff { return [[_myStuff retain] autorelease]; } and -(void)setMyStuff:(id)newStuff { [newStuff retain]; [_myStuff release]; _myStuff = newStuff }, then always use the accessors outside of init and dealloc, and you can't really go wrong.
Comment 3 by Jeff http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment3 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment3 Tip: my mantra during initial setup is "Add an IBOutlet, Add an NSAssert()" to ensure that I remember to connect it up.

As I recall, Apple disagree with you on using accessors in dealloc, specifically in the area of view management - it was something like "unless you nil the view member via the accessor it doesn't get cleaned up" - don't quote me on that though. The principle, however, was that if someone has subclassed you and started sending notifications, its their responsibility to have stop sending notifications. There shouldn't be anything a subclass can do that it can't undo.

And as to

#define MyPrettyColour "MyPrettyColour"

I always make the symbol *different* to the value - that prevents people from misunderstanding and/or accidentally interchanging them.

Initialising variables to nil is a fine thing except that it nukes the sometimes helpful 'using uninitialised variable' warning which nearly always points you at logic errors.
Comment 2 by Michelle http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment2 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment2 Maybe the solution to the Weak Reference issue (e.g. NSTimer still having a reference to NSWindow after it is released) is to have NSTimer invoke a function in the NSWindowController instead?
Comment 1 by Brian Webster http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment1 http://www.zathras.de/angelweb/blog-defensive-coding-in-objective-c.htm#comment1 Brian Webster writes:
I actually go the opposite direction when it comes to using -autorelease. I try to use -release wherever I can, because it makes it a lot easier to debug objects that are getting releaseed one too many times. If you autorelease everything, this often results in your crash coming when the autorelease pool is drained, rather than the point in the code where you did the actual release.

These kinds of bugs can be pretty messy to track down, whereas if it crashes immediately when you call -release, it gives you a stack trace directly where the extra release is occurring. I guess I also tend to be the type to have a single return at the end of my methods, so releasing at the end of the method is no big deal.