[RFC] Throwing an exception with null pointers

Walter Bright newshound2 at digitalmars.com
Wed Apr 16 18:18:43 UTC 2025


I confess I don't understand the fear behind a null pointer.

A null pointer is a NaN (Not a Number) value for a pointer. It's similar (but 
not exactly the same behavior) as 0xFF is a NaN value for a character and NaN is 
a NaN value for a floating point value.

It means the pointer is not pointing to a valid object. Therefore, it should not 
be dereferenced. To dereference a null pointer is:

A BUG IN THE PROGRAM

When a bug in the program is detected, the only correct course of action is:

GO DIRECTLY TO JAIL, DO NOT PASS GO, DO NOT COLLECT $200

It's the same thing as `assert(condition)`. When the condition evaluates to 
`false`, there's a bug in the program.

A bug in the program means the program has entered an unanticipated state. The 
notion that one can recover from this and continue running the program is only 
for toy programs. There is NO WAY to determine if continuing to run the program 
is safe or not.

I did a lot of programming on MS-DOS. There is no memory protection there. 
Writing through a null pointer would scramble the operating system tables, which 
meant the operating system would do something terrible. There were many times 
when it literally scrambled my hard disk. (I made lots of backups.)

If you haven't had this pleasure, it may be hard to realize what a godsend 
protected memory is. A null pointer no longer requires reinstalling the 
operating system. Your program simply quits with a stack trace.

With the advent of protected mode, I immediately ceased all program development 
in real mode DOS. Instead, I'd fully debug it in protected mode, and then as the 
very last step I'd test it in real mode.

Protected mode is the greatest invention ever for computer programs. When the 
hardware detects a null pointer dereference, it produces a seg fault, the 
program stops running and you get a stack trace which gives you the best chance 
ever of finding the cause of the seg fault.

A lovely characteristic of seg faults is they come FOR FREE! There is zero cost 
to them. They don't slow your program down at all. They do not add bloat. It's 
all under the hood.

The idea that a null pointer is a billion dollar mistake is just ludicrous to 
me. The real mistake is having unchecked arrays, which don't get hardware 
protection, and are the #1 source of malware injection problems.

Being unhappy about a null pointer seg fault is like complaining that the 
seatbelt left a bruise on your body as it saved you from your body being broken 
(this has happened to me, I always always wear that seatbelt!).

Of course, it is better to detect a seg fault at compile time. Data Flow 
Analysis can help:

```d
int x = 1;
void main()
{
     int* p;
     if (x) *p = 3;
}
```
Compiling with `-O`, which enables Data Flow Analysis:
```
dmd -O test.d
Error: null dereference in function _Dmain
```
Unfortunately, DFA has its limitations that nobody has managed to solve (the 
halting problem), hence the need for runtime checks, which the hardware does 
nicely for you.

Fortunately, D is powerful enough so you can make a non-nullable type.

In summary, the notion that one can recover from an unanticipated null pointer 
dereference and continue running the program is a seriously bad idea. There are 
far better ways to make failsafe systems. Complaining about a seg fault is like 
complaining that a seatbelt left a bruise while saving you from being maimed.


More information about the Digitalmars-d mailing list