On Fri, Dec 16, 2016 at 1:59 PM, Andrey Semashev
On Fri, Dec 16, 2016 at 12:24 PM, Andrey Semashev < andrey.semashev@gmail.com
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
On Sat, Dec 17, 2016 at 12:11 AM, Emil Dotchevski
wrote: like this to the boost::exception class:
void (*stack_trace_[10])();
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 tradeoff.
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 linker parameters. Emil