diff --git a/build/has_addr2line.cpp b/build/has_addr2line.cpp index e14843c..df5fc74 100644 --- a/build/has_addr2line.cpp +++ b/build/has_addr2line.cpp @@ -1,11 +1,13 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include - -int main() { +#include +#include +int main(int /*argc*/, const char* argv[]) { + std::string s = "addr2line -e " + argv[0] + " 0"; + return std::system(s.c_str()); } diff --git a/build/has_backtrace.cpp b/build/has_backtrace.cpp index 94dcf78..b242bb3 100644 --- a/build/has_backtrace.cpp +++ b/build/has_backtrace.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/build/has_windbg.cpp b/build/has_windbg.cpp index 32724cb..55ff1cb 100644 --- a/build/has_windbg.cpp +++ b/build/has_windbg.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 054ae73..0854ad7 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -1,4 +1,4 @@ -# Copyright Antony Polukhin 2016. +# Copyright Antony Polukhin 2016-2017. # Use, modification, and distribution are # subject to the Boost Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,7 @@ doxygen autodoc \"BOOST_STATIC_CONSTEXPR=static constexpr\" \\ \"BOOST_STACKTRACE_FUNCTION\" \\ \"BOOST_STACKTRACE_DOXYGEN_INVOKED\"" - "boost.doxygen.reftitle=Boost.Stacktrace Header Reference" + "boost.doxygen.reftitle=Reference" ; xml stacktrace : stacktrace.qbk : autodoc ; @@ -31,7 +31,7 @@ boostbook standalone : stacktrace : - boost.root=http://www.boost.org/doc/libs/1_61_0 + boost.root=http://www.boost.org/doc/libs/1_63_0 # boost.root=../../../.. pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html ; diff --git a/doc/stacktrace.qbk b/doc/stacktrace.qbk index 71ec6aa..7ccd441 100644 --- a/doc/stacktrace.qbk +++ b/doc/stacktrace.qbk @@ -1,7 +1,7 @@ [library Boost.Stacktrace [quickbook 1.6] [version 1.0] - [copyright 2016 Antony Polukhin] + [copyright 2016-2017 Antony Polukhin] [category Language Features Emulation] [license Distributed under the Boost Software License, Version 1.0. @@ -15,8 +15,6 @@ How can one display the call sequence in C++? What function called the current f Boost.Stacktrace library is a simple C++03 library that provides information about call sequence in a human-readable form. -[warning This is not an official Boost library! It wasn't reviewed and can't be downloaded from www.boost.org. This library is available to the community to know real interest and get comments for refinement. The intention is to submit library for formal review, if community thinks that it is interesting!] - [endsect] [section Getting Started] @@ -51,7 +49,7 @@ Code from above will output something like this: 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 + 5# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6 6# _start ``` @@ -128,16 +126,15 @@ We've defined the `BOOST_ENABLE_ASSERT_DEBUG_HANDLER` macro for the whole projec ``` Expression 'i < N' is false in function 'T& boost::array::operator[](boost::array::size_type) [with T = int; long unsigned int N = 5ul; boost::array::reference = int&; boost::array::size_type = long unsigned int]': out of range. Backtrace: - 0# boost::stacktrace::detail::backend::backend(void**, unsigned long) - 1# boost::assertion_failed_msg(char const*, char const*, char const*, char const*, long) at boost/libs/stacktrace/example/assert_handler.cpp:38 - 2# boost::array::operator[](unsigned long) - 3# bar(int) at boost/libs/stacktrace/example/assert_handler.cpp:16 - 4# foo(int) at boost/libs/stacktrace/example/assert_handler.cpp:24 - 5# bar(int) at boost/libs/stacktrace/example/assert_handler.cpp:20 - 6# foo(int) at boost/libs/stacktrace/example/assert_handler.cpp:24 - 7# main at boost/libs/stacktrace/example/assert_handler.cpp:53 - 8# __libc_start_main - 9# _start + 0# boost::assertion_failed_msg(char const*, char const*, char const*, char const*, long) at ../example/assert_handler.cpp:39 + 1# boost::array::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-gnu/libc.so.6 + 8# 0x0000000000401139 ``` Now we do know the steps that led to the assertion and can find the error without debugger. @@ -147,21 +144,21 @@ Now we do know the steps that led to the assertion and can find the error withou [section Exceptions with stacktrace] -You can provide more information along with exception by embedding stacktraces into the exception. For that you will need to: +You can provide more information along with exception by embedding stacktraces into the exception. There are many ways to do that, here's how to doe that using Boost.Exception: -* Write a basic class that holds the stacktrace: +* Declare a `boost::error_info` typedef that holds the stacktrace: [getting_started_class_traced] -* Write a helper class for appending class `traced` to any exception: +* Write a helper class for throwing any exception with stacktrce: [getting_started_class_with_trace] -* Throw `with_trace` instead of just `Exception`: +* Use `throw_with_trace(E);` instead of just `throw E;`: [getting_started_throwing_with_trace] -* Catch exceptions by `traced`: +* Process exceptions: [getting_started_catching_trace] @@ -169,18 +166,15 @@ Code from above will output: ``` 'i' must not be greater than zero in oops() -Backtrace: - 0# boost::stacktrace::detail::backend::backend(void**, unsigned long) - 1# traced::traced() at boost/libs/stacktrace/example/throwing_st.cpp:20 - 2# with_trace::with_trace(char const (&) [44]) at boost/libs/stacktrace/example/throwing_st.cpp:33 - 3# oops(int) - 4# bar(int) at boost/libs/stacktrace/example/throwing_st.cpp:70 - 5# foo(int) at boost/libs/stacktrace/example/throwing_st.cpp:75 - 6# bar(int) at boost/libs/stacktrace/example/throwing_st.cpp:65 - 7# foo(int) at boost/libs/stacktrace/example/throwing_st.cpp:75 - 8# main at boost/libs/stacktrace/example/throwing_st.cpp:93 - 9# __libc_start_main -10# _start + 0# void throw_with_trace(std::logic_error const&) at ../example/throwing_st.cpp:22 + 1# oops(int) at ../example/throwing_st.cpp:38 + 2# bar(int) at ../example/throwing_st.cpp:54 + 3# foo(int) at ../example/throwing_st.cpp:59 + 4# bar(int) at ../example/throwing_st.cpp:49 + 5# foo(int) at ../example/throwing_st.cpp:59 + 6# main at ../example/throwing_st.cpp:76 + 7# 0x00007FAC113BEF45 in /lib/x86_64-linux-gnu/libc.so.6 + 8# 0x0000000000402ED9 ``` [endsect] @@ -229,7 +223,7 @@ my_signal_handler(int) at boost/libs/stacktrace/example/debug_function.cpp:21 [section Global control over stacktrace output format] -You may control maximal stacktrace length using [macroref BOOST_STACKTRACE_DEFAULT_MAX_DEPTH] and even override the behavior of default stacktrace output operator by defining the macro from Boost.Config [macroref BOOST_USER_CONFIG] to point to a file like following: +You may override the behavior of default stacktrace output operator by defining the macro from Boost.Config [macroref BOOST_USER_CONFIG] to point to a file like following: [getting_started_user_config] @@ -241,11 +235,10 @@ Code from above will output: ``` Terminate called: - 0# boost::stacktrace::detail::backend::backend(void**, unsigned long) - 1# bar(int) - 2# foo(int) - 3# bar(int) - 4# foo(int) + 0# bar(int) + 1# foo(int) + 2# bar(int) + 3# foo(int) ``` [endsect] @@ -254,15 +247,13 @@ Terminate called: [section Build Macros] -By default Boost.Stacktrace is a header-only library and it attempts to detect the tracing backend automatically. - -You can define the following macros to explicitly specify backend that you're willing to use in header-only mode (those macros have no effect if defined *BOOST_STACKTRACE_LINK* or *BOOST_STACKTRACE_DYN_LINK*): +By default Boost.Stacktrace is a header-only library. You can define the following macros to tune the library (those macros have no effect if defined *BOOST_STACKTRACE_LINK* or *BOOST_STACKTRACE_DYN_LINK*): [table:config_macro Config Macro [[Macro name] [Effect] [Platforms] [Uses debug information [footnote This will provide more readable backtraces if the binary is built with debug information.]] [Uses dynamic exports information [footnote This will provide readable function names in backtrace for functions that are exported by the binary.]] ] - [[*BOOST_STACKTRACE_USE_BACKTRACE*] [Use libbackend. Requires linking with libdl and libbackend libraries.] [GCC/MinGW/Clang...] [yes] [yes]] + [[*BOOST_STACKTRACE_USE_NOOP*] [Use noop tracing that does nothing. Use this if you wish to disable backtracing, `stacktrace::size()` with that macro always returns 0. ] [All] [no] [no]] + [[*BOOST_STACKTRACE_USE_BACKTRACE*] [Use libbacktrace. Requires linking with libdl and libbacktrace libraries.] [GCC/MinGW/Clang...] [yes] [yes]] [[*BOOST_STACKTRACE_USE_ADDR2LINE*] [Use addr2line program to retrive stacktrace. Requires linking with libdl library.] [GCC/MinGW/Clang...] [yes] [yes]] - [[*BOOST_STACKTRACE_USE_NOOP*] [Use noop tracing that does nothing. Use this if you wish to disable backtracing, `stacktrace::size()` with that macro always returns 0. ] [All] [yes] [no]] ] @@ -275,9 +266,9 @@ You may use the following macros to improve build times or to be able to switch If one of the link macros is defined, you have to manually link your binary with one of the libraries that has the tracing implementation: -* boost_stacktrace_unwind -* boost_stacktrace_windbg * boost_stacktrace_backtrace +* boost_stacktrace_basic +* boost_stacktrace_windbg * boost_stacktrace_noop [endsect] diff --git a/example/assert_handler.cpp b/example/assert_handler.cpp index 8c62f6b..e853ffe 100644 --- a/example/assert_handler.cpp +++ b/example/assert_handler.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/example/debug_function.cpp b/example/debug_function.cpp index 2da6cef..7589450 100644 --- a/example/debug_function.cpp +++ b/example/debug_function.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/example/terminate_handler.cpp b/example/terminate_handler.cpp index c115352..bc41775 100644 --- a/example/terminate_handler.cpp +++ b/example/terminate_handler.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -41,6 +41,7 @@ void my_terminate_handler() { void my_signal_handler(int signum) { ::signal(signum, SIG_DFL); + //boost::stacktrace::this_thread_frames::dump("backtrace_file.txt") boost::stacktrace::stacktrace bt; if (bt) { std::cerr << "Signal " << signum << ", backtrace:\n" << boost::stacktrace::stacktrace() << '\n'; // ``[footnote Strictly speaking this code is not async-signal-safe, because it uses std::cerr. [link boost_stacktrace.build_macros_and_backends Section "Build, Macros and Backends"] describes async-signal-safe backends, so if you will use the noop backend code becomes absolutely valid as that backens always returns 0 frames and `operator<<` will be never called. ]`` diff --git a/example/throwing_st.cpp b/example/throwing_st.cpp index 11c0f3e..7d18b8b 100644 --- a/example/throwing_st.cpp +++ b/example/throwing_st.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -6,37 +6,21 @@ #include -#if defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -int main(){} - -#else - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //[getting_started_class_traced #include +#include -struct traced { - const boost::stacktrace::stacktrace trace; - - virtual const char* what() const noexcept = 0; - virtual ~traced(){} -}; +typedef boost::error_info traced; //] //[getting_started_class_with_trace -template -struct with_trace : public Exception, public traced { - template - with_trace(Args&&... args) - : Exception(std::forward(args)...) - {} - - const char* what() const noexcept { - return Exception::what(); - } -}; +template +void throw_with_trace(const E& e) { + throw boost::enable_error_info(e) + << traced(boost::stacktrace::stacktrace()); +} //] //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -49,9 +33,9 @@ BOOST_NOINLINE void bar(int i); BOOST_NOINLINE void oops(int i) { //[getting_started_throwing_with_trace if (i >= 4) - throw with_trace("'i' must be less than 4 in oops()"); + throw_with_trace(std::out_of_range("'i' must be less than 4 in oops()")); if (i <= 0) - throw with_trace("'i' must not be greater than zero in oops()"); + throw_with_trace(std::logic_error("'i' must not be greater than zero in oops()")); //] foo(i); std::exit(1); @@ -80,18 +64,15 @@ int main() { //[getting_started_catching_trace try { foo(5); // testing assert handler - } catch (const traced& e) { - std::cerr << e.what() << '\n'; - if (e.trace) { - std::cerr << "Backtrace:\n" << e.trace << '\n'; - } /*<-*/ std::exit(0); /*->*/ } catch (const std::exception& e) { - std::cerr << e.what() << '\n'; /*<-*/ std::exit(3); /*->*/ + std::cerr << e.what() << '\n'; + const boost::stacktrace::stacktrace* st = boost::get_error_info(e); + if (st) { + std::cerr << *st << '\n'; /*<-*/ std::exit(0); /*->*/ + } /*<-*/ std::exit(3); /*->*/ } //] - + return 5; } -#endif - diff --git a/example/trace_addresses.cpp b/example/trace_addresses.cpp index f55fb3d..1161211 100644 --- a/example/trace_addresses.cpp +++ b/example/trace_addresses.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/example/user_config.cpp b/example/user_config.cpp index 0784747..3bdac10 100644 --- a/example/user_config.cpp +++ b/example/user_config.cpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/example/user_config.hpp b/example/user_config.hpp index 894f452..98fa6fa 100644 --- a/example/user_config.hpp +++ b/example/user_config.hpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/stacktrace.hpp b/include/boost/stacktrace.hpp index a69b872..53793c6 100644 --- a/include/boost/stacktrace.hpp +++ b/include/boost/stacktrace.hpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/stacktrace/detail/frame_noop.ipp b/include/boost/stacktrace/detail/frame_noop.ipp index 5edded5..3594359 100644 --- a/include/boost/stacktrace/detail/frame_noop.ipp +++ b/include/boost/stacktrace/detail/frame_noop.ipp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/stacktrace/detail/frame_unwind.ipp b/include/boost/stacktrace/detail/frame_unwind.ipp index 01f4508..def8f9d 100644 --- a/include/boost/stacktrace/detail/frame_unwind.ipp +++ b/include/boost/stacktrace/detail/frame_unwind.ipp @@ -58,7 +58,9 @@ public: std::string operator()(const void* addr) { Base::res.clear(); Base::prepare_function_name(addr); - if (Base::res.empty()) { + if (!Base::res.empty()) { + Base::res = boost::stacktrace::detail::try_demangle(Base::res.c_str()); + } else { Base::res = to_hex_array(addr).data(); } diff --git a/include/boost/stacktrace/detail/libbacktrace_impls.hpp b/include/boost/stacktrace/detail/libbacktrace_impls.hpp index 29f1588..4730a14 100644 --- a/include/boost/stacktrace/detail/libbacktrace_impls.hpp +++ b/include/boost/stacktrace/detail/libbacktrace_impls.hpp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016. +// Copyright Antony Polukhin, 2016-2017. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/stacktrace/frame.hpp b/include/boost/stacktrace/frame.hpp index b2d7d60..eaefa8b 100644 --- a/include/boost/stacktrace/frame.hpp +++ b/include/boost/stacktrace/frame.hpp @@ -168,6 +168,18 @@ std::basic_ostream& operator<<(std::basic_ostream