Betteridge’s law of headlines and an idea of how methods work in most programming languages work you’d think the answer would be no. But the answer is closer to yes! I mean otherwise why even bother writing this? Technically what happens is undefined (so never rely on this behavior) but normally it works or at least it doesn’t crash immediately.

For example this program:

Produces this output.

❯ ./nullptr
constructed
I just print
I print the member variable
m_member: initialized
I just print
I print the member variable
[1]    39881 segmentation fault  ./nullptr

This, at least to me, is counterintuitive. I first ran into this issue debugging a failed test that was segfaulting at strange place. It was in the middle of a method that was accessing a member variable. Before the failure the method had been called on stack allocated object but for various reasons someone had changed it to a pointer and it wasn’t being initialized. This test has some issues with layers of indirection so this wasn’t immediately obvious to the person changing things but that’s another issue.

Now at first I couldn’t understand why calling this method on a nullptr wasn’t crashing until I remembered that C++ is different from other object oriented languages I’m used to. Specifically, non virtual C++ methods aren’t dynamically dispatched. This makes things faster because there’s no work to dynamically figure out where the method is all that’s needed is a callq __ZN3Foo13member_accessEv and we’re off. Since that’s all that’s needed to call a method and since doing any more could slow things down that’s all the compiler does. Well generally. One could probably do something different if they wanted but most compilers are going to do this. So where does the crash come from? Like clearly you can’t access the member variable of the object that doesn’t exist but what exactly is happening? You can call a method on an object that doesn’t exist so maybe there’s some other weirdness at play.

Most methods in object oriented languages have a keyword like self or this that let you refer to the object the method is being called on. In some languages you have to mention the this or self to get an object’s property inside a method but in most (that I’ve used) you just need to use the properties name. Regardless there needs to be a reference to the object to find things out about the object like the values of the member variables. In most languages the reference to the object is implicitly passed in to method but in languages like python you need to let the language know you’re passing it like so def method(self, other_parameters). In C++ the reference to the object is called this and it’s implicitly passed. But it is passed! And that’s where the crash happens. During runtime the method tries to dereference the this pointer plus the offset for the member you’re referencing. this however is null so you’re really trying to reference something between 0x0 and 0x0 + sizeof(YourObject) which is still in all likelihood not in your program’s memory space so you get an access violation and crash.

I mentioned virtual methods earlier. When you invoke a virtual method on a nullptr you do crash immediately. Why the difference? Because virtual methods are dynamically dispatched! That’s why they exist! So there at least what I expect happen.

So to sum up you can call a non virtual method on a typed null pointer but the result is undefined. Undefined generally means running the method ‘normally’ until you attempt to access a member variable (or anything that would dereference the this pointer which includes things like virtual methods) at which point your program will try and access NULL (or something close to it) and crash.