[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