Programs crash for a reason! Crashing when faced with nonsense is a good thing! Let us not forget this.
Programs crash for a reason! Crashing when faced with nonsense is a good thing! Let us not forget this.
(Note: I, myself, do not ever rely on this functionality, and even disagree with it, but the context in which people use it is important to understand when judging it; and with that context, I consider my own objections mostly due to my biases and not something that I would argue is "correct".)
(Of course, no compilers actually do precisely that, but it is possible for compilers to delete virtual method calls entirely if it can prove the receiver had to be null...)
class Example {
public:
static bool do_it;
virtual void do_it_if() {
if (g_do_it) return;
/* otherwise do something that dereferences this... */
}
};
void test1() {
Example::do_it = false;
static_cast<Example *>(NULL)->do_it_if();
}
void test2() {
Example::do_it = true;
static_cast<Example *>(NULL)->do_it_if();
}
In the above code, only test2 crashes (clang 6.0). If crashing was defined behavior you would need an extra check in the code generated for do_it_if.EDIT:
Also, it's worth explaining why test1 works even though do_it_if is virtual. Since there aren't any methods that override do_it_if, the virtual method lookup can be elided and you don't have to dereference this to find the vtable. If do_it_if had been overridden and the runtime type was unknown, you would need to dereference this to lookup do_it_if in the vtable, which would segfault in both tests.
I have a feeling it wouldn't work well in practice if you made the handler raise an exception. As the author notes, you're not the only one sending messages, and Cocoa will probably crash your program with a nil message send sooner or later. But you might be able to use it to find out where it's happening, at least.
if (input == nil)
haltAndCatchFire();
Or whatever the Objective-C syntax for that is.I was imagining something more like a modified version of the runtime's objc_msgSend() C function (which Obj-C method invocations get compiled into) that guarded against that, but you do make me realize that such checks could conceivably be automatically tacked on at build time.
Anyway, I'm not entirely sure how useful such a thing would be, but I am curious how often my code (unintentionally) makes calls against nil and I've just never noticed because it doesn't cause harm.
Static analysis could potentially go a long way here to expose values that could be potentially "infected" with nil. (And, for all I know, the JVM JIT could do exactly this to skip checks on provably non-null values.)
The first thing objc_msgSend does is check if foo is nil and, if so, returns 0/nil/the all-zero bit pattern/whatever. It can be extremely convenient, but it can also be extremely inconvenient.
Anyway, I'll carry on reading my ObjC book as obviously the language has uses, although there's a Swift book in the post. Which do I read first though, eh?