[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