On 4/29/21 11:55 AM, Edward Catmur wrote:
> Crashing is not the desired behavior. If it is possible to shut down
> cleanly (flushing logs, raising incidents, releasing resources) then it
> is better to do so.
When we talk about bugs, the faster you crash the better. As you said
yourself, at this point your data cannot be trusted, and any pending
results may be invalid. So the best course of action is to crash early,
with a core dump, so that the bug is fixed. Graceful termination only
complicates investigation; it doesn't provide you a reliable result of
the operation.
Yes, from the point of view of investigation it's best to core dump and crash. But graceful termination may be necessary in the business environment.
> Exceptions result from a program arriving in an unexpected state; thus
> they are a bug, as we consider it.
No, an exception is a way to signal an exceptional (abnormal, atypical,
unacceptable) situation. That situation is nonetheless expected, hence
the code is written to handle it with an exception being thrown.
If you don't use exceptions for control flow, then they can be used to terminate more-or-less gracefully in unexpected situations where the program can identify that its state is unexpected.
The amount of work that is done during the stack unwinding is
dynamic and may not involve anything you listed. And that work is
necessary to continue operation (i.e. catch the exception, process it
and go on). Capturing a stacktrace likely has larger algorithmic
complexity (as it has to unwind beyond the exception handler) and it is
not necessary to continue operation. It may improve diagnostics, yes,
but it is not necessary for the program to continue running.
It is not necessary to unwind beyond the exception handler. The stack portion from throw point to handler is sufficient for investigation.
And allocating memory during an exception throw is also not good in its
own right. There is a case of an exception being thrown in low memory
conditions.
That's a corner case; certainly if there is insufficient memory to store the stack trace it should be omitted. But again - is an allocation of ~80 bytes really apt to fail even under memory pressure?
> The compiler can determine whether those could be called by the handler,
> and suppress stacktrace if they are not.
In general, no it can't. Static code analysis doesn't work when you need
a definitive answer because the compiler may not see the whole program.
If you're using exceptions for control flow the compiler will be able to see the whole of the program accessible from the catch block.
The only case when you'd use std::nested_exception is when you catch one
exception (say, from library A), and you want to transform it to your
own domain (say, that of your library B), and you want to retain the
original for better diagnostics or special handling in the caller. Then
you would wrap the original exception in std::nested_exception and throw
it as your exception of domain B. Note that the caller would be catching
exception of domain B, he will not be able to catch an exception of
domain A. And that is exactly what is intended in this case.
Yes, that's the normal case.
> https://www.boost.org/doc/libs/1_76_0/libs/exception/doc/get_error_info.html
> <https://www.boost.org/doc/libs/1_76_0/libs/exception/doc/get_error_info.html>
>
> The ability to format all attached data along with the exception itself
> (https://www.boost.org/doc/libs/1_76_0/libs/exception/doc/diagnostic_information.html
> <https://www.boost.org/doc/libs/1_76_0/libs/exception/doc/diagnostic_information.html>)
>
> is just a cherry on top.
>
> That only works if you know the type of the item. There's no way to
> iterate over items of unknown type individually.
Ok, but do you need to iterate? In order to process the attached data,
you do need to know its type anyway, so I see no problem here.
You have the type and the value converted to string (type-erased on construction). That's all you need for diagnostics.