In C++, does dereferencing a nullptr itself cause undefined behaviour, or is it the acting upon the dereferenced pointer which is undefined

cpointersundefined-behavior

I happen to have a reason why I might want to dereference a nullptr.

Of course when I do, my program crashes, and from what I gather, this is due to the compiler playing it safe and stopping my program, rather than risking the program acting upon the dereferenced nullptr, which is undefined behaviour.

So my question is to affirm this:

  1. Is it my compiler crashing my program, or the "undefined behaviour"?
  2. If it is the compiler, suppose it didn't choose to crash the program, is the act of dereferencing the pointer in any way able to cause something to happen that could alter the behaviour of the program writ large? This is assuming that nothing is done to it at all, like so:
void moot()
{
        QString *s{nullptr};
        *s;
}
  1. Continued: Could I hypothetically run moot() thousands of times without any "undefined behaviour" taking place?
  2. If true, what if I did not do anything to the object, but I did pass it around, like so:
void receiveCC( QString         ) { return; }
void receiveR ( QString &       ) { return; }
void receiveCR( const QString & ) { return; }

void moot()
{
        QString *s{nullptr};
        *s;
        receiveCC(*s);
        receiveR (*s);
        receiveCR(*s);
}
  1. Continued: Same as above; could such be done without any "Undefined behaviour" taking place?

Best Answer

It is not the compiler that causes your program to crash on dereferencing a null pointer. The problem is that the pointer is pointing to memory that it is illegal to reference, and the operating system kills your program for invalid behavior.

Trying to trick the compiler by obfuscating that it is a null pointer won't work, because it isn't the compiler that detects it.

There is no legitimate reason to dereference a null pointer unless you on a rare system that maps page zero (or you intend your program to crash). It is generally accepted that zeroing a pointer is a good way to mark it as invalid and dereferencing an invalid pointer is a bug. Modern operating systems do not give you a page of memory at that address specifically to make debugging invalid pointers easier.

I would not even call your program crashing from this to be undefined behavior. Dereferencing a pointer with random data in it would give you undefined behavior. Dereferencing a pointer that contains an address not assigned to your program is quite well defined in demand paged memory protected operating systems, and the behavior defined by the operating system is for your program to crash. From the language's perspective, it is still undefined behavior, because what happens is not defined in the scope of the language. Since this behavior is undefined by the language, the compiler can do nothing about it and should do nothing about it.

The exception to this is systems that have no memory protection and systems that intentionally map page zero. Some older systems do this, but most of the modern systems that do are microcontrollers, some of which might even have memory mapped I/O or some other special purpose memory in page zero.

Since null pointer dereferences are typically bugs, it is unlikely a compiler would bother to optimize away null pointer dereferences or put guard code around a possible one, as this would not improve code performance. If they did even bother to detect this, they would do it to emit a warning to assist you in debugging, similar to the "code not reachable" warning. The only reason for the compiler to generate different code around one would be if it knew what you were trying to do.

Related Topic