Subject: Re: [boost] [Stacktrace] review
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2016-12-16 17:49:25
On Fri, Dec 16, 2016 at 1:59 PM, Andrey Semashev <andrey.semashev_at_[hidden]>
> On Sat, Dec 17, 2016 at 12:11 AM, Emil Dotchevski
> <emildotchevski_at_[hidden]> wrote:
> > On Fri, Dec 16, 2016 at 12:24 PM, Andrey Semashev <
> >> wrote:
> >> The backtrace itself is not a lightweght object
> > Yes it is. It's basically a list of pointers and we can cap it by default
> > at, say, 10.
> > Just to be clear, I'm talking about adding the equivalent of something
> > this to the boost::exception class:
> > void (*stack_trace_)();
> What happens when the backtrace exceeds this limit? Would it be
> possible to attach backtraces larger than that?
We capture the top 10, or maybe the top 32. This puts a limit to both the
space and speed overhead of capturing the stack trace.
> Adding an array of pointers to the base class of exceptions is also
> not free. Whether one uses stacktraces or not, all Boost exceptions
> become 80 bytes larger regardless. For comparison, std::runtime_error
> in gcc 6 takes 16 bytes (not counting the string, if it's dynamically
> allocated and not stored in-place). Not that I have thousands
> exceptions stored somewhere, but that doesn't look like a reasonable
In C++, it is unspecified how much memory is required to throw an
exception. By definition, throwing an exception may require a memory
allocation, which might fail with std::bad_alloc. That said, I've never
seen this in practice, I don't think we should be concerned.
> >> so the overhead of the generic Boost.Exception machinery is probably not
> >> significant. And if that overhead is significant then maybe it could be
> >> optimized instead. After all, why have it if we don't want to use it.
> > The cost of using the generic Boost Exception machinery is not limited to
> > speed and space but also coupling. The boost::throw_exception function
> > template is not coupled with any Boost libraries, while Boost Exception
> > itself uses e.g. shared_ptr and a few others. That said, even the runtime
> > cost of the generic Boost Exception machinery is probably an order of
> > magnitude bigger than storing 10 pointers.
> Thing is, the 10 pointers affect everyone, including those not using
> the backtraces.
True, so do capturing __FILE__ and __LINE__. I'm not suggesting that
capturing the stack trace by default is free, only that it is the better
compromise (pending looking at the actual implementation).
> They also affect boost::exception interface making it
> more like a swiss knife with a bunch of case-specific APIs.
Not really, like __FILE__ and __LINE__, the data captured by the stack
trace would be available through the usual boost::get_error_info interface;
the fact that there is special handling of this data is an implementation
detail not exposed in the API.
> That means
> everyone using boost::exception are coupled with whatever is present
> with those APIs. You described the 10 pointers, but I don't think you
> would expose that array as is from boost::exception - if only for type
> safety, you would want to wrap it into a class or something.
No, it would be an array of pointers, or maybe just an array of bytes that
a boost::get_error_info specialization will know how to deal with. That
part of Boost Exception may be coupled with Stacktrace, that's fine.
> > Requiring to link the Windows kernel? That's a breaking change, too.
> But you do have to link something to obtain the backtrace. You're not
> planning to implement it inline in the header, for all platforms, do
> you? :)
I don't know, but I wouldn't exclude that as a possibility. If the goal is
to make this as lightweight as possible so that the stacktrace can be
reasonably captured by default, why not? As a general rule, I think that it
is permissible to use compiler-specific APIs that don't require explicit
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk