C++ Logo

std-proposals

Advanced search

Re: Stacktrace from exception

From: Andrey Semashev <andrey.semashev_at_[hidden]>
Date: Thu, 29 Apr 2021 00:54:01 +0300
On 4/28/21 11:51 PM, Edward Catmur via Std-Proposals wrote:
> On Wed, 28 Apr 2021 at 20:23, Andrey Semashev via Std-Proposals
> <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>>
> wrote:
>
> IMO, exceptions thrown by the standard library are close to useless.
> Not
> in least part for the poor QoI of the standard libraries in this
> regard,
> as many of them don't produce an informative error message with any
> relevant information. Also because the standard library cannot provide
> any context-specific details about the error (i.e. std::vector::at
> cannot know what the vector is and where the index comes from, only the
> caller knows that and can provide that information in the log). For
> this
> reason, you should normally code so that you check the necessary
> preconditions in your code before calling the standard library, and
> then
> call standard library methods that don't throw.
>
>
> Absolutely. But bugs occur, and we call third-party library code that
> may also have bugs.

In case of a bug let it crash and collect the stacktraces then
(possibly, with a core dump). If the bug leads to an exception - debug
it once (with a debugger, logging, stacktraces - whatever means
necessary), write a test, and then forget it. You will never see that
exception again, and you will never need stacktraces automatically
attached to exceptions.

But normally, an exception is not a bug but rather an exceptional
situation. As opposed to a bug, an exception is the intended reaction to
some input. Here, a stacktrace usually is not that interesting.

> Quite the opposite. What you're suggesting is a recipe for a system
> vulnerable to DoS. Yes, you would log the error, and you would possibly
> log multiple times before throttling. But you do want to dispatch
> errors
> efficiently to have some time for processing valid data or requests.
>
> Not a concern, to be honest. Once a bug has been identified, all data
> processed by the program is suspect, so even if the choice taken is to
> keep running (and not shutdown safely) you'll likely have to rerun anyway.

Again, an exception is not a bug. If your system routinely receives
invalid requests, you want to deal with them fast so that valid requests
still get to be processed.

> I'm opposed to doing this *implicitly* and *by default*. On the
> contrary, I would welcome the feature if it was defined as explicitly
> requested by the user.
>
> Also fine - as long as all of std::current_exception_stacktrace()
> std::current_exception(), and throw; constitute an explicit request.

The stacktrace must have been collected by the time when these functions
are called. So no, they don't count as a request.

> > Well, obviously you'd use both std::nested_exception and
> > Boost.Exception, not to mention your own exception hierarchy
> inheriting
> > from both. And std::exception is polymorphic, as is
> boost::exception, so
> > almost all of the time (except with some really old libraries)
> there's
> > no problem using dynamic_cast.
>
> Most types that you'd want to attach won't be polymorphic.
>
> Sure, so you dump them into your holds-anything exception object that is
> mixed with std::nested_exception.

Again, why would you mess with std::nested_exception?

> > The point of std::nested_exception is more that it allows you to
> attach
> > your own exception hierarchy to an existing exception of
> arbitrary type.
>
> And why would you do that? I mean, unless you do literally have
> multiple
> exceptions that you want to chain together, why would you want to wrap
> your data, like std::stacktrace for example, into another exception
> type, just to use it with std::nested_exception? Which is not designed
> to work as a container of arbitrary data in the first place to boot?
>
> No, there's no need to pull an owl on a globe since boost::exception
> can
> already be a base class for an exception, and provides the necessary
> infrastructure for adding and extracting the attached data.
>
> Every library has its own exception hierarchy; hopefully they're
> polymorphic and with luck they are based on std::exception or
> boost::exception. But if they aren't, you have to deal with them anyway.

I think, you missed my point. You don't attach exceptions, you attach
arbitrary data that is not an exception to an exception. Furthermore,
you may attach the same kind of data to different types of exceptions.
And preferably you shouldn't be required to write an exception class for
every such combination.

> Exceptions are never going to be efficient or elegant; whatever you can
> get to work is good enough. As for attaching data, boost::exception is
> nice enough, but it doesn't provide the necessary fine-grained access to
> individual data items; all you can do is convert them to string
> representation en bloc.

Oh, no, you very much can access individual items, that's the point.

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)
is just a cherry on top.

Received on 2021-04-28 16:54:07