Misleading headline and final sentence. The whole point of the article is that it's not dereferencing NULL. It's just passing NULL as a hidden parameter to a function, which in turn ignores that parameter.
I also found it rather odd that the author spent so much time defining what a pointer is and what dereferencing is, when the article won't be of any interest whatsoever to someone who doesn't already know these things.
And lastly, when I saw the headline about dereferencing NULL, I expected it to be a discussion regarding the circumstances in which you can actually map address 0 to valid memory (and therefore dereference NULL without crashing), and the consequences thereof.
It's disappointing that this works so reliably, even with the simplest of examples. I would have thought that if the compiler could resolve the function call statically it would do away with the vtable lookup, but neither g++ nor Clang do so at any level of optimisation.
Well, you see, that would change the behavior of the program. In order for it to resolve the vtable statically, which it CAN do, it would have to know what kind of vtable the NULL cowPointer has. And the true answer is that the program is already wrong once it accesses the vtable.
To put it another way, such an optimizer would transform incorrect programs into correct programs.
If you write correct programs, the optimization is useless since it only transforms incorrect programs. If you write incorrect programs, the optimization is dangerous since it makes it harder for you to figure out that your program is wrong.
True, it's not dereferencing NULL at the machine level, but in C++ terms, it really is dereferencing the pointer. Evaluating the expression "p" (or "p->m", which is equivalent to "(p).m") is dereferencing. What it isn't doing is reading or writing at or near location 0.
According to [1] this is (strictly speaking) undefined behaviour. It also won't work with virtual function calls, because they'll try to access the vtable and segfault.
If your compiler isn't cheeky you can use this stuff in funny ways with constructs like `if(this)` in your member functions. Technically such a check could be optimised out because `this==null` can only result from undefined behaviour, but in practice it probably won't be.
This reminds me of a conversation I had with a coworker recently about how possible it would be a for an object to check itself for null. Based on this explanation, it seems like this would definitely be possible in C++ (our conversation was in the context of Java, but it's interesting from an academic perspective)
Technically I look at methods as functions with a hidden first parameter that accepts a pointer to the class object's data. If you don't try to dereference that pointer, then the function should work like static member.
I was wondering if the compiler will add some check code preventing me from calling any method on a NULL pointed obj. But obviously its permitting it.
Of course virtual methods are different. Then you are calling a pointer to a function, the address of which should be stored in your obj data structure.
Actually, the last example won't even run because cout doesn't have the >> stream operator. Not sure how identical code samples in the same article could get those mixed up, unless the author typed each example out manually.
Not really contributing to the conversation, but it jumped out at me.
Fun fact: There are a number of platforms that made NULL dereference valid (usually returning zero), because it enables you to do fun compiler optimizations that are not safe otherwise. Some of these optimizations relate to being able to insert new loads or hoist existing ones, some of these relate to being able to remove null pointer checks.
(for example, in:
int **a = NULL;
int *b = NULL;
int c = 0;
...
if (a ! = NULL)
b = *a;
if (b != NULL)
c = *b;
you can remove all the NULL checks if *NULL = 0)
AIX was an example of such a platform (at least until version 5.3, i haven't used it since then).
TL;DR version: the '->' operator is punned in C++ to mean both "load through a pointer" and "call a function with the pointer as the first argument." Unsurprisingly, nothing blows up when you use the second form with a null pointer.
V8 actually uses this to implement a pretty cool trick. V8 objects are tagged--tag bits distinguish valid pointers from integer immediate values. The integer class has no data, it stores its information in the 'this' pointer.
I also found it rather odd that the author spent so much time defining what a pointer is and what dereferencing is, when the article won't be of any interest whatsoever to someone who doesn't already know these things.
And lastly, when I saw the headline about dereferencing NULL, I expected it to be a discussion regarding the circumstances in which you can actually map address 0 to valid memory (and therefore dereference NULL without crashing), and the consequences thereof.