[OT] OT: Null checks.

Timon Gehr timon.gehr at gmx.ch
Tue May 6 03:05:30 UTC 2025


On 5/6/25 02:04, Walter Bright wrote:
> On 5/4/2025 1:06 PM, Timon Gehr wrote:
>> My understanding is all of those features are under constant threat of 
>> being broken for "Error" and not guaranteed to work in the first place.
> 
> We learned our lesson to not break existing code. For example, we 
> deprecated use of complex numbers maybe 15 years ago, and yet there's 
> still active code using them. This is annoying to me because it makes 
> doing the AArch64 code generator significantly harder.
> ...

Well, personally I am mostly upset about this deprecation because 
`creal` was my favorite D keyword. 😋

Also I had actually bought the justification for why they were built-in.

> 
>>> Worst case, you can write a signal handler for any of the signals 
>>> that can be generated (not just null pointer signals), and have the 
>>> handler write all it can to a file that can be emailed to you.
> 
> I asked grok "write a signal handler for linux that catches a null 
> pointer seg fault":
> ...

Sure, it's not rocket science. Anyway, if you recall, the mysterious 
crash was on _Windows_, on a machine I do not control. I am sure I will 
be able to get out stack traces on segfault there too using SEH and by 
perhaps shipping debug info.

I can solve or work around problems. However, I think it is better to 
eliminate said problems at the source, for everyone.

The point is:

- by default you just get nothing. even if druntime prints a stack trace 
(which it might do on windows, I am not a windows user myself, so have 
not seen that), I suspect it just deletes the console window immediately 
anyway.

- you have to do some manual steps, which you most likely only do once 
you actually face an irreproducible issue

- you have to wait for the next report, which may be months later (and 
next report is not the same as the next time it happens, as I don't like 
putting telemetry in my software)

- running the scope guards as advertised fixes the issue, e.g. on 
Windows I wrapped the main function in:

```d
try ...
catch(Throwable e){
     writeln(e.toString());
     system("pause");
     return 1;
}
```
This way my users can actually see the stack trace in cases where it is 
actually printed. And even before that, _other scope guards will have 
gathered useful information related to the crash beyond just a call 
stack trace_.

- cases where destructors/scope guards used to run are actively being 
broken so that scope guards no longer run. Branches are actively being 
coded into druntime to result in invalid instruction errors even if the 
programmer does not compile with a flag that means they want this. This 
has to stop, it's terrible UX.


>>> You can also hook atexit() as maybe your program is exiting that way.
>>
>> Well, yes. As I said, I can probably figure it out at some point. It's 
>> just a lot more work than necessary in some other languages for 
>> comparable situations.
> 
> https://man7.org/linux/man-pages/man3/atexit.3.html
> 
> ```
> #include <stdlib.h>
> 
> int atexit(typeof(void (void)) *function);
> 
> DESCRIPTION
> 
> The atexit() function registers the given function to be called at
> normal process termination, either via exit(3) or via return from
> the program's main().  Functions so registered are called in the
> reverse order of their registration; no arguments are passed.
> ```

Sure. I guess I could try to put the `system("pause")` call into this 
instead, then at least stderr will be visible to users somewhat more 
often, even in cases where scope guards are skipped entirely.

The entire point though is that I do not want destructors and scope 
guards to be skipped. x) None of your proposed workarounds so far fix this.

The additional work I am referring to is mostly _fixing the issue with 
only bare-bones information_ and _waiting for the next report_. I care 
less about _getting the program to spit out more than zero information 
on crash_. It seems you misunderstood me. Adding signal handlers is a 
nuisance, but this is not what causes the bulk of additional work. I do 
consider it a waste of time in its own right, though.


Of course, there will always be situations where destructors/scope 
guards don't run, e.g., if there is a hardware or power failure, but 
there can at least be a best effort to run them instead of actively 
working to suppress them. It will be sufficient in almost all cases.

Unless you are saying actually running the destructors and scope guards 
is similarly easy, I have not dug this deep into druntime so far. Then 
it should maybe be officially supported at least in an opt-in fashion. 
Also I suspect grok would be of limited utility for making this work, if 
doing so in a signal handler is even workable.

I understand that in cases where there is memory corruption you may not 
actually want to run them, but I feel D in standard usage is memory safe 
enough for me to make the call that running them always if possible at 
all will be overall vastly more helpful than running them unreliably.


More information about the Digitalmars-d mailing list