Boost logo

Boost :

Subject: Re: [boost] [stacktrace] review
From: Antony Polukhin (antoshkka_at_[hidden])
Date: 2017-03-10 04:27:05


std::cout << symbol_location_ptr(f.address()); // outputs `some/path/test.exe`

2017-03-08 22:59 GMT+03:00 mbartosik via Boost <boost_at_[hidden]>:
> I see that Boost.stacktrace is up for review March 17, 2017 - March 26, 2017
>
> I've got some broad feedback. I'm in a race to comment before I go on
> vacation on Friday, so I'm sorry if I've missed something or misunderstood.
> I will try and follow the thread while on vacation - but not sure that will
> happen.

Thanks a lot for the feedback!

> 1) Resolving function names can be VERY expensive. Potentially it requires
> multi-megabyte files to be loaded and parsed. It is not clear to me that the
> resolution of frame.name() is going to be deferred. I have written a _lot_
> of stack tracing code, and have usually in practice needed something that is
> fast and efficient to collect stack trace(s), but which allows deferring of
> the cost of resolving symbolic information until I really need it. In the
> extreme example I had some code which speculatively collected 100,000's of
> stack traces, but only symbolically resolved 10's of them. Thus the
> gathering of the 100,000's of traces had to be very very efficient (only the
> return addresses being saved) but the symbolic resolution did not have to be
> so fast. This also solved the issue of working within signals which I also
> had to do, indeed the code had been used to arguably work at an even lower
> level than signal handlers -- but more on that would get off topic.
>
> I think that the interface needs to reflect this. Or at a minimum clearly
> state that symbol resolution will be delayed until absolutely necessary -- I
> think that it is best if the interface reflects this.
>
> In addition to my own code, the company I currently work for has a
> multi-platform stack trace library which also defers symbols resolution.
>
> Also until the symbols are resolved I think that the space requirement for a
> frame should be kept to the minimum (i.e. one pointer). This may necessitate
> two classes e.g. raw_stacktrace and symbolic_stacktrace with a means to
> convert between them, the symbolic_stacktrace should be all that is needed
> by default i.e. for most simple case users, potentially that means that
> having stacktrace and raw_stacktrace is better (raw_stacktrace only having a
> single pointer for each raw_frame).

boost::stacktrace::stacktrace class only stores raw pointers. Names
resolving happens only when you call frame::name(). I'll update the
docs to make that more explicit.

I see no need in `symbolic_stacktrace` because such class
* usable only if multiple frame::name() calls for the same frame
happen (which is a very rare case)
* could be easily build by users

Tell me if I'm wrong or missed some point.

> 2) Tracing optimized code on some architectures can be really quite
> difficult. Especially when there are performance constraints (for example on
> Microsoft x86 should FPO information be loaded, should the whole .pdb file
> be loaded to walk the stack). So I would suggest a user specified function
> could be used to provide some choice in the algorithm for how walk the stack
> back, with some default.

How does such function shall look like? Could you please give an example?

> 3) Modules / libraries. Something else I have found useful is the ability to
> examine a frame and find out the code module e.g. a .dll or .so from it.
> That then raises the possibility of another object in addition to stacktrace
> and frame. Members that I have found useful on a module object are things
> like path, load address, length (maybe begin/end for the address in memory),
> name, version, copyright notice (this can get rather platform specific).

This is a part of Boost.DLL library. In boost_1_64 it will have a
`boost::dll::symbol_location_ptr` so you can write the following code:

stacktrace st; // no symbol names extraction, only storing frame addresses
frame f = st[0]; // copying a pointer under the hood
std::cout << f; // outputs `foo() at source/path/foo.cpp:42`. Only at
this line function name and source location are retrieved.

> A boost::stacktrace is definitely needed. I'm hoping that we'll get one that
> can meet more than the simple case needs.
>
> - Mark

Great thanks for the feedback! Are there more usecases that the
library does not meet?

-- 
Best regards,
Antony Polukhin

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk