
On Sat, Dec 17, 2016 at 12:11 AM, Emil Dotchevski
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 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? 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.
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. They also affect boost::exception interface making it more like a swiss knife with a bunch of case-specific APIs. 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. That class will have some methods to work with the stacktrace, and so on. That is beside the fact that given there is Boost.Stacktrace library, that class doesn't really belong to Boost.Exception or throw_exception.
How old? I mean, it only has to support the oldest compiler Boost libraries support.
Yes, which is very old. :) Anyway, the point is that boost::throw_exception must remain extremely lightweight in terms of dependencies AND it must be very conservative in terms of using C++ features. Specifically, I am hinting that std synchronization facilities are off-limits
Intrinsics are still available.
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? :) Anyway, if everything's off limits then the only thing I can suggest is to leave throw_exception as is and create a separate macro/function with support for backtraces.