What is the point of nothrow?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed Jun 13 20:08:06 UTC 2018


On Wednesday, June 13, 2018 10:56:41 wjoe via Digitalmars-d-learn wrote:
> On Wednesday, 13 June 2018 at 03:14:33 UTC, Jonathan M Davis
>
> wrote:
> > Most programs do not handle the case where they run out of
> > memory and cannot continue at that point. For better or worse,
> > D's GC was designed with that in mind, and it treats failed
> > allocations as an Error. In the vast majority of cases, this is
> > desirable behavior. In those cases when it isn't, alternate
> > memory allocation schemes such as malloc can be used. But
>
> But manual memory management sucks and is a huge waste of
> everyone's time and I was hoping to get the best from both worlds
>
> :)
> :

Well, I think that the reality of the matter is that the number of programs
that even attempt to recover from not having enough memory is extremely
small such that you're dealing with a very niche case if you're going to try
it, and if the GC fails to allocate more memory for you, your options are
typically pretty limited. So, even if the GC provided a way to allocate
memory that returned null on failure instead of throwing an Error, I don't
know that it would do you a lot of good, but regardless, the GC was not
designed with that in mind, and even GC.malloc throws OutOfMemoryError on
allocation failure rather than null. So, there isn't much choice on the
matter.

> > regardless of whether the decision to treat failed memory
> > allocations as an Error was a good one or not, the fact remains
> > that as soon as an Error is thrown, you lose the ability to
> > deal with things cleanly, because full clean up is not done
> > when an Error is thrown (and can't be due to things like how
> > nothrow works). So, regardless of whether a failed memory
> > allocation is a condition that can be recovered from in
> > principle, the way that D handles GC allocations make it
> > unrecoverable in practice - at least as far as GC-allocated
> > memory is concerned.
>
> Did I get that right?
> You say when an error is thrown destructors, scope statements,
> etc. are not executed - if declared as nothrow because the
> exception handler mechanism stuff is missing, is that correct?
> And it does execute if not declared as nothrow but can't be
> relied upon because some other  nothrow functions could have
> omitted some of those statements?

Yes, and there's no guarantee that clean-up will occur even if nothing is
nothrow. While the current implementation will do clean-up in those cases,
it didn't used to, and Walter has repeatedly stated that it is not
guaranteed to do so. Errors are _not_ intended to be caught and recovered
from. They're essentially a segfault that prints a message and stack trace
but which for some reason uses the exception throwing mechanism to get to
the code that prints the message and exits the program.

> So I shoot myself in the foot with nothrow and if I don't use it
> I'm still in a world of hurt?
>
> I understand the idea that an Error is not supposed to be caught
> but why would such a 'feature' be desirable? Where's the benefit
> if nothing can be relied upon ?
>
> If all errors would be treated like an exception, the developer
> could decide whether it is an error which needs to terminate
> right away or be able to handle the issue and continue or
> gracefully shutdown.

The idea is that because your program is in an invalid state, attempting a
graceful shutdown is unsafe. But regardless of whether you agree with that,
the fact that nothrow doesn't do clean-up pretty much ensures that it isn't
safe in the general case, and nothrow can't do clean-up without negating one
of the main reasons that it exists in the first place - which is to improve
performance by not emitting exception-handling code.

> Could even set a break point or force a core
> dump right there.

The fact that Errors don't immediately kill the program and instead sort of
unwind the stack is a definite problem for getting good debug information on
crashes. I suspect that Walter doesn't quite understand the issues here,
because whenever anyone raises issues related to stuff like this, he has a
tendancy to basically tell people to rerun their program - which works
fantastically in the world he typically programs in (compilers) but doesn't
work very well with stuff like OSes or server programs where you frequently
have no clue how to replicate the problem. My guess is that Errors work they
do in part because he's not used to debugging situations where a coredump
being created at the point of failure the first time it happens (rather than
during attempts to reproduce the problem) is what you really need.

I think that the reasons that this is not a bigger problem than it is stem
primarily from the fact that Errors are going to be very rare in production
code unless it wasn't properly tested. So, the problem shouldn't pop up
often. However, when it does, having a coredump at the site of the failure
would definitely be valuable.

> If the exception would be ignored the program will crash
> regardless but at least there would be a stack trace that I could
> rely upon instead of this unreliable and possibly corrupt state
> which is good for nothing.
>
> This concept is a bit like color everyone with the same brush or
> one shoe fits all. Where in reality it depends on the
> circumstances whether it is an error or an exception.
> But maybe I feel that way because currently there's a bit of a
> blur regarding what's defined as Errors and Exceptions.
>
> Anyways I took a lot from your awesome explanations so far.
> Thanks a ton!

Personally, I'm increasingly of the opinion that having Errors was a mistake
and that the better solution would have been to just print out the error
message and stack trace right there and immediately kill the program. That
would then give you a coredump exactly where you were and avoid all of the
confusion about Errors being thrown but not really doing proper clean-up. I
don't know why Walter decided to do it the way he did, particularly since
he's made it very clear that the entire point of Errors is to indicate a
fatal error in the program, that doing any clean-up at that point is
dangerous, and that the program needs to terminate, not try to recover.

But I don't think that changing it so that Errors terminated immediately
(and thus gave you a coredump for that spot in the program) would change
what's an Error and what's an Exception. Either way, Errors are for error
conditions that are deemed to be unrecoverable. So, it wouldn't change the
fact that trying to recover from an Error is a terrible idea. It would just
make it so that Errors which occurred in programs would then be more
debuggable - especially in the rare cases that they happen in production.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list