Exception/Error division in D
Jonathan M Davis
jmdavisProg at gmx.com
Wed May 30 14:36:50 PDT 2012
On Wednesday, May 30, 2012 17:29:30 Don Clugston wrote:
> On 30/05/12 12:59, Jonathan M Davis wrote:
> > On Wednesday, May 30, 2012 11:32:00 Don Clugston wrote:
> >> On 30/05/12 10:40, Jonathan M Davis wrote:
> >>> On Wednesday, May 30, 2012 10:26:36 deadalnix wrote:
> >>>> The fact that error don't trigger scope and everything is nonsensial.
> >>>
> >>> If an Error is truly unrecoverable (as they're generally supposed to
> >>> be),
> >>> then what does it matter? Something fatal occured in your program, so it
> >>> terminates. Because it's an Error, you can get a stack trace and report
> >>> something before the program actually terminates, but continuing
> >>> execution after an Error is considered to be truly _bad_ idea, so in
> >>> general, why does it matter whether scope statements, finally blocks, or
> >>> destructors get executed? It's only rarer cases where you're trying to
> >>> do
> >>> something like create a unit test framework on top of assert that you
> >>> would need to catch an Error, and that's questionable enough as it is.
> >>> In
> >>> normal program execution, an error is fatal, so cleanup is irrelevant
> >>> and
> >>> even potentially dangerous, because your program is already in an
> >>> invalid
> >>> state.
> >>
> >> That's true for things like segfaults, but in the case of an
> >> AssertError, there's no reason to believe that cleanup would cause any
> >> damage.
> >> In fact, generally, the point of an AssertError is to prevent the
> >> program from entering an invalid state.
> >
> > An assertion failure really isn't all that different from a segfault. By
> > definition, if an assertion fails, the program is an invalid state,
> > because the whole point of the assertion is to guarantee something about
> > the program's state.
>
> There's a big difference. A segfault is a machine error. The integrity
> of the machine model has been violated, and the machine is in an
> out-of-control state. In particular, the stack may be corrupted, so
> stack unwinding may not be successful.
>
> But, in an assert error, the machine is completely intact; the error is
> at a higher level, which does not interfere with stack unwinding.
>
> Damage is possible only if you've written your destructors/finally code
> extremely poorly. Note that, unlike C++, it's OK to throw a new Error or
> Exception from inside a destructor.
> But with (say) a stack overflow, you don't necessarily know what code is
> being executed. It could do anything.
There is definitely a difference in severity. Clearly memory corruption is more
severe than a logic error in your code. However, in the general case, if you
have a logic error in your code which is caught by an assertion, there's no
way to know without actually examining the code how valid the state of the
program is at that point. It's in an invalid state _by definition_, because the
assertion was testing the validity of the state of the program, and it failed.
So, at that point, it's only a question of degree. _How_ invalid is the state?
Since there's no way for the program to know how severe the logic error was,
it has no way of knowing whether it's safe to run any cleanup code (the same
as the program has no way of knowing whether a segfault is relatively minor -
e.g. a null pointer - or absolutely catastrophic - e.g. memory is horribly
corrupted).
If you got an OutOfMemoryError rather than one specifically indicating a logic
error (as with Errors such as AssertError or RangeError), then that's
specifcally telling you that your program has run out of a particular resource
(i.e. memory), which means that any code which assumes that that resource is
available (which in the case of memory is pretty much all code) will fail.
Running cleanup code could be very precarious at that point if it allocates
any memory (which a lot of cleanup code wouldn't, but I'm sure that it would
be very easy to find cleanup code which did). Any further attempts at
allocation would result in more OutOfMemoryErrors and leaving the cleanup code
only partially run, thereby possibly making things even worse, depending on
what the cleanup code does.
Running cleanup code is _not_ safe when an Error is thrown, because the
program is definitely in an invalid state at that point, even if it's not as
bad as a segfault can be.
Now, it may be that that risk is worth it, especially since a lot of the time,
cleanup code won't be invalidated in the least by whatever caused Errors
elsewhere in the program, and there are definitely plenty of cases where at
least attempting to cleanup everything is better than skipping it all due of
an Error somewhere else in the program. But it's still not safe. It's a
question of whether we think that the risks posed by trying to run cleanup
code after the program is in an invalid enough state that an Error was thrown
are too great to attempt cleanup or whether we think that the problems caused
by skipping that cleanup are greater.
> > Now, if a segfault occurs (particularly if it's caused by something
> > other than a null pointer), the program is likely to be in a _worse_
> > state,
> > but it's in an invalid state in either case. In neither case does it make
> > any sense to try and recover, and in both cases, there's a definite risk
> > in executing any further code - including cleanup code.
> >
> > Yes, the segfault is
> > probably worse but not necessarily all that much worse. A logic error can
> > be just as insidious to the state of a program as memory corruption,
> > depending on what it is.
>
> I'm surprised by your response, I didn't think this was controversial.
> We could just as easily have said assert() throws an AssertException.
> (Or have two kinds of assert, one which is an Error and the other merely
> an Exception).
In general, a segfault is definitely worse, but logic errors can_ be just as
bad in terms of the damage that they can do (especially in cmparison with
segfaults caused by null pointers as opposed to those caused by memory
corruption). It all depends on what the logic error is and what happens if you
try and continue with the program in such a state.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list