On the D Blog--Symphony of Destruction: Structs, Classes, and the GC

Mike Parker aldacron at gmail.com
Fri Mar 5 03:27:29 UTC 2021


On Thursday, 4 March 2021 at 23:42:58 UTC, Dukc wrote:

>
> I don't understand this part. If an assert was failing, the 
> program is going to terminate anyway, so 
> InvalidMemoryOperationError is no problem. Well, it might 
> obfuscate the underlying error if there is no stack trace, but 
> banning `assert`ing in anything that could be called by a 
> destructor sounds too drastic to me. Even the lowest level 
> system code tends to contain asserts in D, at least in my 
> codebase. If asserting is banned, destructors can do faily much 
> nothing. I'd think it's much more practical to redefine the 
> assert failure handler if InvalidMemoryOperationError due to a 
> failed assert is a problem.

Yes, this can be worked around. Passing -checkaction=C to the 
compiler will use the C assert handler and no exception will be 
thrown (which, IMO, should be the default behavior of asserts 
anyway). But even then, I believe as a general rule that any code 
which touches an assert has no place in a finalizer. And that's 
because asserts are inherently deterministic.

A properly-written assert is used to verify an expectation that 
the program is in a specific state at a specific point in its 
execution. If the program is not in that state at that point, 
then we know we've got an error in our code. It's because of this 
determinism that we can remove asserts from released code and 
expect that nothing will break, and it's why we don't assert on 
conditions that are beyond our control (like user input).

Because finalizers are non-deterministic, they kill that "at a 
specific point in the program's execution" part, rendering any 
asserts they touch unreliable. It is realistically possible that 
an assert invoked in a finalizer never triggers during 
development, then the program is released with asserts removed, 
and then it breaks out in the wild because a finalizer is invoked 
at a point when the program isn't in the expected state.

This doesn't make *destructors* useless, but *finalizers* really 
are mostly useless most of the time, IMO. As D programmers, we 
need to consciously be aware of the distinction since the 
language isn't.




More information about the Digitalmars-d-announce mailing list