[OT] OT: Null checks.

Timon Gehr timon.gehr at gmx.ch
Sun May 4 03:48:49 UTC 2025


On 5/4/25 03:19, Walter Bright wrote:
>> In practice (outside your small DMC compiler backend box), you can only dereference a non-null pointer, so dereferencing a nullable pointer is actually explicitly one of the cases where you convert it to a non-nullable one...
> 
> ```
> int main()
> {
>     int* p = (int*)0;
>     int& q = *p;
>     return q;
> }
> ```
> ```
> g++ x.c
> ./a.out
> Segmentation fault (core dumped)
> ```

$ clang++ -O2 x.c
clang: warning: treating 'c' input as 'c++' when in C++ mode, this 
behavior is deprecated [-Wdeprecated]
$ ./a.out
$ echo $?
48

This is not only the case in C. Translate the example to D and compile 
with LDC with optimizations enabled. You will most likely see zero 
segfaults.

I am sorry, but your position is simply untenable.

> 
>> Furthermore, there are no null checks when you pass a dereferenced null pointer to a `ref` parameter.
> 
> That's right. And if you access such a ref parameter, you get a seg fault. Not UB.
> 

You may or may not get a seg fault, because it is indeed UB. Potentially 
on some random non-computer person's Windows machine, at a location that 
is even further away from where the problem was than the original faulty 
dereference. It also may or may not crash at the location where you 
dereference the invalid `ref` parameter.

On an somewhat related note: in D you can currently create invalid 
non-null pointers in `@safe` code by exploiting the lack of checks.

> 
>> Also, a segfault on some user's machine is a lot less useful than even a stack trace,
> 
> That's why the D runtime intercepts the seg fault and gives a stack trace. gdb will also give a stack trace.
> ...

All I am seeing is that sometimes user's programs close and they are not 
giving me any further information because they don't really know how to 
use a computer and it happens infrequently enough that they don't care 
enough to try to figure out how to help me out. This may be a null 
dereference, or it could be something else. Maybe it even prints a stack 
trace on Windows, but the console window closes on them immediately or 
something. Who knows what actually is happening. I am not seeing this on 
my machine...

I can probably try to set up some other way to debug that then gets 
flagged as malware even harder. However, none of this is necessary in 
the first place. If my `scope(exit)` ran they would be able to 
immediately provide all the info I need, as was the case with a couple 
thrown Exceptions and Errors in the past.


>> and being able to collect some crash info in a `scope(failure)` or similar is even more useful. It can reduce a month-long heisenbug hunt into a 15 minute fix.
> 
> I have a *lot* of experience chasing down null pointer violations in real mode DOS. None of them took me a month. I think the worst one took 3 days. As soon as I got my hands on a protected mode 286 system, I immediately switched all development to it, because of the null pointer hardware protection. Big productivity increase! After that, I only compiled the real mode version as the very last thing after all tests passed.
> ...

Well congrats, seems your bugs were reproducible on your own machine and 
at a frequency of more than once every couple of months. I don't even 
know if the crashes are my fault or not. Maybe they even happen in some 
dependency, which I would know if D's error handling was more useful.

> (The worst heisenbug problems I had were the result of uninitialized variables. Any changes at all to the code caused the problems to shift around. This is why D initializes all variables.)
> 
> 
>> `assert(0)` in druntime is a similarly frustrating experience.
> 
> Why? You can set assert(0) to do one of several things, including calling your own custom handler. By default it'll tell you the file and line of the failure. I use assert(0) all the time as a debugging tool.
> ...

AFAIU the default druntime ships with `-release`.

> 
>> If there were a flag to enable null checks on any nullable pointer dereference, I would enable it immediately in all my projects.
> 
> I would be very curious how much larger and slower the resulting executables would be.
> 
> P.S. Why would CPU designers put null checks in the hardware if it was so useless?
> ...

It's not useless for everything, it's just useless for some things. Your 
anecdotes are unfortunately not universal and also things changed.


> P.P.S. `scope(failure)` is not intended for catching `Error`, although it does. There's a PR to fix it to only catch `Exception`, but that failed in the test suite. 

This is heart-shattering news. If this ever gets pulled without any 
option to revert I will no longer be able to justify using the official 
D releases for anything.


More information about the Digitalmars-d mailing list