On Sat, Dec 17, 2016 at 9:32 PM, Antony Polukhin wrote:
I'd like to discuss a proposed changes. Thing that I'm worried about:
* replacing class `stacktrace` with vector will definitely
break the most common use case std::cout << get_stacktrace(); as it's
not a good idea to overload ostream operator for vector of void
pointers
No, I wasn't suggesting to replace `stacktrace` with `vector`.
I was suggesting it as a possible implementation of `stacktrace` (i.e.
an internal data member of the `stacktrace` class). And BTW, that
should probably be `vector<frame>` to support proper container
semantics in `stacktrace`.
I've given it some more thought after I wrote the review, and it
occurred to me that the main reason for the current implementation of
`basic_stacktrace` as an array is probably the intention to allow its
use in signal handlers. For some reason it didn't occur to me while I
was writing the review. That is a fair goal, although I'm having a
hard time thinking of what can be done with a stacktrace from a signal
handler. I guess, the only thing that can be done is dumping it into a
file, but the library does not provide such a facility (the
`operator<<` is not suitable for this).
Of course, `vector` is not an option in a signal handler, but the
runtime-sized `basic_stacktrace` can still be used in this case. The
idea is to offer a way to provide an external storage for the
`basic_stacktrace` object, which would be an array of `frame`s in this
case. It could look something like this:
void my_signal_handler(int sig)
{
boost::stacktrace::frame frames[10];
boost::stacktrace::stacktrace bt{ frames, 10 }; // bt.size() == 0
&& bt.capacity() == 10
boost::stacktrace::fill_stacktrace(bt); // makes bt.size() <= 10
}
Internally, `stacktrace` should be smart enough to handle three cases
wrt. the buffer of frames:
1. The `stacktrace` object refers to an external buffer. It should not
deallocate the frames.
2. The `stacktrace` object owns a small amount of frames stored in the
internal array (e.g. up to 8 frames). The frames should be destroyed
with the `stacktrace` object.
3. The `stacktrace` object owns a large amount of frames, allocated
dynamically on heap. The frames should be destroyed and deallocated
with the `stacktrace` object.
Copying and assignment should also work with these three states.
* addr2line and forking is not nice. Is linking with a GPL licensed
code an acceptable alternative?
I think it would be difficult to get it accepted, but probably
possible if it's a separate header, on which nothing from the rest of
the library depends. Of course, the most preferable solution is to
have the whole library licensed under BSL.
Maybe there is a different implementation of the functionality
provided by addr2line? Niall mentioned a tool from LLVM, maybe its
code can be reused (and I'm assuming it's licensed under BSD).
* removing `basic_stacktrace` will definitely remove all the
possibilities for optimization of caching COM/parsed DWARF. This is a
quick win that later may turn into big troubles.
Again, I wasn't suggesting to remove `stacktrace` - on the contrary,
the stacktrace should be represented with a distinct type. What I'm
having the problem with is what semantics you put into that type.