Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Getting Started

How to print current call stack
Better asserts
Handle terminates
Stacktrace from arbitrary exception
Exceptions with stacktrace
Enabling and disabling stacktraces
Saving stacktraces by specified format
Getting function information from pointer
Global control over stacktrace output format

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] 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-