What is the point of nothrow?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Jun 14 19:06:07 UTC 2018


On Thursday, June 14, 2018 18:11:20 wjoe via Digitalmars-d-learn wrote:
> On Wednesday, 13 June 2018 at 20:08:06 UTC, Jonathan M Davis
> wrote:
> > On Wednesday, June 13, 2018 10:56:41 wjoe via
> > 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
>
> that fact also means that a program which threw an Error cannot
> be debugged anymore; because of invalid state you can neither
> know, nor assume, that what you see in your debugger or core dump
> is actually the state which led to the throw.

As I said, personally, I think that the program shut just print and
terminate rather than throwing an Error. Walter seems to have designed
things from the premise that you could rerun the program to reproduce the
problem (which in is usually true with the programs he works on). And in
that case, simply getting the error message and stacktrace would be plenty.
The problem is when you can't simply rerun the program to reproduce the
problem and is why I'm of the opinion that printing and terminating would be
better than throwing an Error.

> > improve performance by not emitting exception-handling code.
>
> if performance matters so much I would use betterC.
>
> 'Improving' performance without profiling and such a trade-off is
> a bad idea. If it were opt in - yes, I know I will get
> undebuggable code on error thrown but I want or need the
> performance gain, fair enough. But instead you are a victim of
> that implementation whether you like it or not and you might not
> even be aware about it.

betterC really has nothing to do with performance. It just has to do with
avoiding druntime so that you can have C code just link in and use the D
code as if it were C (though using it would avoid the issue of Errors, since
the runtime wouldn't be there to handle them). And again, Errors are
intended for fatal cases, so most of the concerns about doing clean-up are
irrelevant. Attempting to recover from an Error is considered to be like
attempting to recover from a segfault, which is a terrible, terrible idea.
And there are plenty of folks who want to be able to have their code be more
performant when it's not using exceptions. So, as long as folks aren't
trying to catch Errors, the fact that nothrow doesn't emit the exception
handling code really isn't a problem.

> Out of curiosity, in case of out of memory, will the program
> crash trying to throw OutOfMemoryError or is it pre-allocated
> along with the memory needed to format and print the message?

OutOfMemoryError is pre-allocated. core.exception's onOutOfMemoryError is
called rather than allocating a new OutOfMemoryError.

> And out of curiosity again, where would I find this place where
> the printing and terminating occurs ?

I'd have to go digging in druntime. I don't know. I've probably seen it
before, but it's not code that I've dealt with often enough to remember
exactly where it is off the top of my head.

> > 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.
>
> Aborting with an error code would be sufficient. No need to print
> anything.
> A backtrace can be obtained in the debugger.

Given that a coredump isn't always generated (and in the case of Windows, I
don't know if they even have an equivalent), printing out the same
information that gets printed out now would often be desirable. It's just
that if it kills the program right there rather than doing any unwinding of
the stack, then the coredump is for the state of the program at the point of
failure like it arguably should be.

> > 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.
>
> No it wouldn't but not everything declared or treated as an error
> in D is one.
>
> There should be only a few and everything else should be an
> Exception.

There are no Errors in druntime or Phobos that I'm aware of where I would
not consider it perfectly reasonable that they're Errors, but there are
cases where it's certainly subjective. At some point, it comes down to a
design decision - e.g. is providing an incorrect index considered a bug or
simply bad input? The choice that Walter went with was that it is a bug, and
that works extremely well overall, but an argument could be made the other
way. It's the same with using contract programming versus defensive
programming. It's a design decision, and not everyone is always going to
agree about design decisions. It's also not necessarily the case that one
way is right and the other is wrong. Sometimes, it's simply a matter of
tradeoffs.

If you don't agree with some of the design decisions, then you will
generally either have to figure out how to work around them for what you
want or just learn to live with them. The same goes for all of us.

In some cases, a DIP could be written and accepted to change the language,
but if your concerns have to do with nothrow not doing clean-up or anything
like that, then I can guarantee that you're wasting your time. There _might_
be a chance of convincing Walter that the program should be terminated at
the point of failure instead of throwing an Error, but there's no way that
he's going to agree that nothrow shouldn't mean that exception handling code
isn't inserted or that the program should be attempting any kind of clean-up
when an Error occurs. He's been _very_ firm about that. An Error is a fatal
condition, and he's absolutely adamant that the best course of action at
that point is to terminate the program and that the program cannot be
trusted to do the right thing once an Error occurs, because by definition,
the fact that an Error occured means that the program is in an invalid
state. Given his attitude, I do find it a bit weird that he went with
throwing Errors rather than just killing the program after printing a
message, but it may have something to do with the state of D1 when he made
that choice. I don't know.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list