C will not throw an exception when you try to dereference a null pointer. C does not have exceptions. Instead, dereferencing a null pointer results in undefined behaviour, which is often tough to deal with. Having an exception thrown is a lot nicer. In C the compiler is free to make optimizations, based on the programmer's vigilance about which pointers may or may not be null, which you would have never expected on your own[1]. Debugging these issues is hell.
I think their point was that in modern languages (not C), having null in the language isn't so bad, as attempts to dereference null are handled fairly safely, generally with exceptions.
Same thing goes with modern languages throwing on signed overflow, where, again, C gives you the horrors of undefined behaviour.
I think the main issue is that the program should never reach a state where you're in a position to dereference a null. If it does, that means you didn't handle an error condition earlier in the program. Sure you can handle the null safely but that doesn't handle the real cause of the error.
The solution is for the language to offer 'option types', which essentially force you to check for null. Zig does this, and the result is much nicer than how things work in C: https://ziglang.org/documentation/master/#Optionals
More importantly, they let you safely not check for null (because with null-types, you should really always be handling it, because anything can go from never-null to null-in-this-one-case without warning)
And options help with solidifying input contract as well as the output. Knowing what's an acceptable input via a type system is just as relevant as knowing what is a potential output.
While an exception might be marginally better than undefined behavior, its actual occurrence can still leave your database in an inconsistent state or have other random detrimental effects. By the time you see the exception reported the damage has already been done (program flow interrupted unexpectedly). Due to the large amount of possible program states you would have to do an impossible amount of testing to make sure such surprises won't happen once the software gets into the hands of a user.
>an exception might be marginally better than undefined behavior
The difference isn't marginal, it's night-and-day. Undefined behaviour means the program can behave in unpredictable ways, either now, or at some other time. If you're lucky, your whole process explodes immediately, but that's not guaranteed. Undefined behaviour is the root of many a nightmarish hidden bug.
> its actual occurrence can still leave your database in an inconsistent state or have other random detrimental effects
Not if your exception-handling code is correct, surely?
I agree though that there are good arguments to be made against exceptions as they exist in many languages, particularly regarding how it interferes with control flow 'from a distance' as it were. I defer to the excellent Raymond Chen: https://devblogs.microsoft.com/oldnewthing/?p=36693
The interesting question is not what you do once a catastrophe has happened (program has reached invalid state) but how to avoid it in the first place. Exceptions are better than undefined behavior in coping with the former, but they still don't help you with the latter. The idea to “make invalid states unrepresentable” would give you an actual shot at this.
> Exceptions are better than undefined behavior in coping with the former, but they still don't help you with the latter
That's not right. Exceptions are thrown reliably and are always 'noisy'. Undefined behaviour may go completely unnoticed for a long time. Code that wrongly throws exceptions tends to get fixed.
I've seen undefined behaviour in code samples in respected technical books. The code happened to work fine when using the MSVC C++ compiler and x84/AMD64 targets, and will probably continue to do so.
> The idea to “make invalid states unrepresentable” would give you an actual shot at this.
That's a pretty good summary of what type-systems research is aiming for.
Not in cases where the optimizer did something tricky based on the assumption that null pointer dereferences never happen (which is allowed because they are undefined behavior so any behavior is correct).
Oh wow, I didn't know you were on here! I'm a huge fan of D so I just wanted to say thanks for all the work you've done. D is an absolute pleasure to work with.
This does not save you if that null pointer is supposed to point to an array, and subsequent index operations move it out of the protected first page (or the first couple, I forget how modern Unix does it).
This is indeed how certain language runtimes generate null pointer exceptions. It would be too slow to add comparisons against null to every use of a pointer. So they handle SIGSEGV and raise the exception if the faulting access is on the null page.
Interesting side question: if you have a struct bigger than a page, and you dereference the end of it... How big does it have to be to not get this behavior?
[1]: <https://www.imperialviolet.org/2016/06/26/nonnull.html>