![]() |
Home | Libraries | People | FAQ | More |
boost::stacktrace::stacktrace
contains methods for working with call-stack/backtraces/stacktraces. Here's
a small example:
#include <boost/stacktrace.hpp> // ... somewhere inside the `bar(int)` function that is called recursively: std::cout << boost::stacktrace::stacktrace();
In that example:
boost::stacktrace::
is the namespace that has all the classes and functions to work with
stacktraces
stacktrace()
is the default constructor call; constructor stores the current function
call sequence inside the stacktrace class.
Code from above will output something like this:
0# bar(int) at /path/to/source/file.cpp:70 1# bar(int) at /path/to/source/file.cpp:70 2# bar(int) at /path/to/source/file.cpp:70 3# bar(int) at /path/to/source/file.cpp:70 4# main at /path/to/main.cpp:93 5# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6 6# _start
![]() |
Note |
|---|---|
By default the Stacktrace library is very conservative in methods to decode stacktrace. If your output does not look as fancy as in example from above, see section "Configuration and Build" for allowing advanced features of the library. |
Pretty often assertions provide not enough information to locate the problem. For example you can see the following message on out-of-range access:
../../../boost/array.hpp:123: T& boost::array<T, N>::operator[](boost::array<T, N>::size_type) [with T = int; long unsigned int N = 5ul]: Assertion '(i < N)&&("out of range")' failed. Aborted (core dumped)
That's not enough to locate the problem without debugger. There may be thousand code lines in real world examples and hundred places where that assertion can happen. Let's try to improve the assertions, and make them more informative:
// BOOST_ENABLE_ASSERT_DEBUG_HANDLER is defined for the whole project #include <stdexcept> // std::logic_error #include <iostream> // std::cerr #include <boost/stacktrace.hpp> namespace boost { inline void assertion_failed_msg(char const* expr, char const* msg, char const* function, char const* /*file*/, long /*line*/) { std::cerr << "Expression '" << expr << "' is false in function '" << function << "': " << (msg ? msg : "<...>") << ".\n" << "Backtrace:\n" << boost::stacktrace::stacktrace() << '\n'; std::abort(); } inline void assertion_failed(char const* expr, char const* function, char const* file, long line) { ::boost::assertion_failed_msg(expr, 0 /*nullptr*/, function, file, line); } } // namespace boost
We've defined the BOOST_ENABLE_ASSERT_DEBUG_HANDLER
macro for the whole project. Now all the BOOST_ASSERT
and BOOST_ASSERT_MSG will
call our functions assertion_failed
and assertion_failed_msg
in case of failure. In assertion_failed_msg
we output information that was provided by the assertion macro and boost::stacktrace::stacktrace:
Expression 'i < N' is false in function 'T& boost::array<T, N>::operator[](boost::array<T, N>::size_type) [with T = int; long unsigned int N = 5ul; boost::array<T, N>::reference = int&; boost::array<T, N>::size_type = long unsigned int]': out of range. Backtrace: 0# boost::assertion_failed_msg(char const*, char const*, char const*, char const*, long) at ../example/assert_handler.cpp:39 1# boost::array<int, 5ul>::operator[](unsigned long) at ../../../boost/array.hpp:124 2# bar(int) at ../example/assert_handler.cpp:17 3# foo(int) at ../example/assert_handler.cpp:25 4# bar(int) at ../example/assert_handler.cpp:17 5# foo(int) at ../example/assert_handler.cpp:25 6# main at ../example/assert_handler.cpp:54 7# 0x00007F991FD69F45 in /lib/x86_64-linux-