summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/stacktrace
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/stacktrace
parentInitial commit. (diff)
downloadceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.tar.xz
ceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/boost/libs/stacktrace/README.md15
-rw-r--r--src/boost/libs/stacktrace/build/Jamfile.v2145
-rw-r--r--src/boost/libs/stacktrace/build/has_addr2line.cpp25
-rw-r--r--src/boost/libs/stacktrace/build/has_backtrace.cpp15
-rw-r--r--src/boost/libs/stacktrace/build/has_windbg.cpp13
-rw-r--r--src/boost/libs/stacktrace/build/has_windbg_cached.cpp28
-rw-r--r--src/boost/libs/stacktrace/example/assert_handler.cpp55
-rw-r--r--src/boost/libs/stacktrace/example/debug_function.cpp33
-rw-r--r--src/boost/libs/stacktrace/example/terminate_handler.cpp326
-rw-r--r--src/boost/libs/stacktrace/example/throwing_st.cpp78
-rw-r--r--src/boost/libs/stacktrace/example/trace_addresses.cpp63
-rw-r--r--src/boost/libs/stacktrace/example/user_config.cpp38
-rw-r--r--src/boost/libs/stacktrace/example/user_config.hpp58
-rw-r--r--src/boost/libs/stacktrace/index.html35
-rw-r--r--src/boost/libs/stacktrace/meta/libraries.json15
-rw-r--r--src/boost/libs/stacktrace/src/addr2line.cpp16
-rw-r--r--src/boost/libs/stacktrace/src/backtrace.cpp16
-rw-r--r--src/boost/libs/stacktrace/src/basic.cpp15
-rw-r--r--src/boost/libs/stacktrace/src/noop.cpp11
-rw-r--r--src/boost/libs/stacktrace/src/windbg.cpp10
-rw-r--r--src/boost/libs/stacktrace/src/windbg_cached.cpp11
-rw-r--r--src/boost/libs/stacktrace/test/Jamfile.v2245
-rw-r--r--src/boost/libs/stacktrace/test/test.cpp282
-rw-r--r--src/boost/libs/stacktrace/test/test_impl.cpp72
-rw-r--r--src/boost/libs/stacktrace/test/test_impl.hpp58
-rw-r--r--src/boost/libs/stacktrace/test/test_noop.cpp58
-rw-r--r--src/boost/libs/stacktrace/test/test_num_conv.cpp71
-rw-r--r--src/boost/libs/stacktrace/test/test_void_ptr_cast.cpp79
-rw-r--r--src/boost/libs/stacktrace/test/thread_safety_checking.cpp72
-rw-r--r--src/boost/libs/stacktrace/test/torture.cpp26
30 files changed, 1984 insertions, 0 deletions
diff --git a/src/boost/libs/stacktrace/README.md b/src/boost/libs/stacktrace/README.md
new file mode 100644
index 000000000..a80427aab
--- /dev/null
+++ b/src/boost/libs/stacktrace/README.md
@@ -0,0 +1,15 @@
+### Stacktrace
+Library for storing and printing backtraces.
+
+[Documentation and examples.](http://boostorg.github.io/stacktrace/index.html)
+
+
+### Test results
+@ | Build | Tests coverage | More info
+----------------|-------------- | -------------- |-----------
+Develop branch: | [![Build Status](https://travis-ci.org/boostorg/stacktrace.svg?branch=develop)](https://travis-ci.org/boostorg/stacktrace) [![Build status](https://ci.appveyor.com/api/projects/status/l3aak4j8k39rx08t/branch/develop?svg=true)](https://ci.appveyor.com/project/apolukhin/stacktrace/branch/develop) | [![Coverage Status](https://coveralls.io/repos/github/boostorg/stacktrace/badge.svg?branch=develop)](https://coveralls.io/github/boostorg/stacktrace?branch=develop) | [details...](http://www.boost.org/development/tests/develop/developer/stacktrace.html)
+Master branch: | [![Build Status](https://travis-ci.org/boostorg/stacktrace.svg?branch=master)](https://travis-ci.org/boostorg/stacktrace) [![Build status](https://ci.appveyor.com/api/projects/status/l3aak4j8k39rx08t/branch/master?svg=true)](https://ci.appveyor.com/project/apolukhin/stacktrace/branch/master) | [![Coverage Status](https://coveralls.io/repos/github/boostorg/stacktrace/badge.svg?branch=master)](https://coveralls.io/github/boostorg/stacktrace?branch=master) | [details...](http://www.boost.org/development/tests/master/developer/stacktrace.html)
+
+
+### License
+Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
diff --git a/src/boost/libs/stacktrace/build/Jamfile.v2 b/src/boost/libs/stacktrace/build/Jamfile.v2
new file mode 100644
index 000000000..6d6d85a9b
--- /dev/null
+++ b/src/boost/libs/stacktrace/build/Jamfile.v2
@@ -0,0 +1,145 @@
+# Copyright (C) 2016-2019, Antony Polukhin.
+#
+# Use, modification and distribution is 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)
+#
+
+project
+ : source-location .
+ : requirements
+ <visibility>hidden
+ ;
+
+lib dl ;
+lib gcc_s ;
+lib Dbgeng ;
+lib ole32 ;
+
+
+local LIBBACKTRACE_PATH = [ modules.peek : LIBBACKTRACE_PATH ] ;
+lib backtrace
+ :
+ : <search>$(LIBBACKTRACE_PATH)/lib <link>static
+ :
+ : <include>$(LIBBACKTRACE_PATH)/include
+ ;
+
+actions mp_simple_run_action
+{
+ $(>) > $(<)
+}
+
+rule mp-run-simple ( sources + : args * : input-files * : requirements * : target-name )
+{
+ exe $(target-name)_exe : $(sources) : $(requirements) ;
+ explicit $(target-name)_exe ;
+ make $(target-name).output : $(target-name)_exe : @mp_simple_run_action ;
+ explicit $(target-name).output ;
+ alias $(target-name) : $(target-name).output ;
+}
+
+mp-run-simple has_backtrace.cpp : : : <library>backtrace : libbacktrace ;
+explicit libbacktrace ;
+
+mp-run-simple has_addr2line.cpp : : : : addr2line ;
+explicit addr2line ;
+
+mp-run-simple has_windbg.cpp : : : <library>Dbgeng <library>ole32 : WinDbg ;
+explicit WinDbg ;
+
+mp-run-simple has_windbg_cached.cpp : : : <library>Dbgeng <library>ole32 : WinDbgCached ;
+explicit WinDbgCached ;
+
+local libraries ;
+
+lib boost_stacktrace_noop
+ : # sources
+ ../src/noop.cpp
+ : # requirements
+ <warnings>all
+ <link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ : # default build
+ : # usage-requirements
+ #<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ ;
+
+libraries += boost_stacktrace_noop ;
+
+lib boost_stacktrace_backtrace
+ : # sources
+ ../src/backtrace.cpp
+ : # requirements
+ <warnings>all
+ <target-os>linux:<library>dl
+ <library>backtrace
+ <link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ [ check-target-builds ../build//libbacktrace : : <build>no ]
+ : # default build
+ : # usage-requirements
+ #<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ ;
+
+libraries += boost_stacktrace_backtrace ;
+
+lib boost_stacktrace_addr2line
+ : # sources
+ ../src/addr2line.cpp
+ : # requirements
+ <warnings>all
+ <target-os>linux:<library>dl
+ <link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ [ check-target-builds ../build//addr2line : : <build>no ]
+ : # default build
+ : # usage-requirements
+ #<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ ;
+
+libraries += boost_stacktrace_addr2line ;
+
+lib boost_stacktrace_basic
+ : # sources
+ ../src/basic.cpp
+ : # requirements
+ <warnings>all
+ <target-os>linux:<library>dl
+ <link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ [ check-target-builds ../build//WinDbg : <build>no ]
+ : # default build
+ : # usage-requirements
+ #<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ ;
+
+libraries += boost_stacktrace_basic ;
+
+lib boost_stacktrace_windbg
+ : # sources
+ ../src/windbg.cpp
+ : # requirements
+ <warnings>all
+ <library>Dbgeng <library>ole32
+ <link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ [ check-target-builds ../build//WinDbg : : <build>no ]
+ : # default build
+ : # usage-requirements
+ #<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ ;
+
+libraries += boost_stacktrace_windbg ;
+
+lib boost_stacktrace_windbg_cached
+ : # sources
+ ../src/windbg_cached.cpp
+ : # requirements
+ <warnings>all
+ <library>Dbgeng <library>ole32
+ <link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ [ check-target-builds ../build//WinDbgCached : : <build>no ]
+ : # default build
+ : # usage-requirements
+ #<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
+ ;
+
+libraries += boost_stacktrace_windbg_cached ;
+
+boost-install $(libraries) ;
diff --git a/src/boost/libs/stacktrace/build/has_addr2line.cpp b/src/boost/libs/stacktrace/build/has_addr2line.cpp
new file mode 100644
index 000000000..763515d5f
--- /dev/null
+++ b/src/boost/libs/stacktrace/build/has_addr2line.cpp
@@ -0,0 +1,25 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <cstdlib>
+#include <string>
+
+#include <boost/config.hpp>
+#include <unwind.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int main() {
+
+#ifdef BOOST_STACKTRACE_ADDR2LINE_LOCATION
+ std::string s = BOOST_STRINGIZE( BOOST_STACKTRACE_ADDR2LINE_LOCATION );
+ s += " -h";
+#else
+ std::string s = "/usr/bin/addr2line -h";
+#endif
+
+ return std::system(s.c_str());
+}
diff --git a/src/boost/libs/stacktrace/build/has_backtrace.cpp b/src/boost/libs/stacktrace/build/has_backtrace.cpp
new file mode 100644
index 000000000..68664dd95
--- /dev/null
+++ b/src/boost/libs/stacktrace/build/has_backtrace.cpp
@@ -0,0 +1,15 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <backtrace.h>
+#include <unwind.h>
+
+int main() {
+ backtrace_state* state = backtrace_create_state(
+ 0, 1, 0, 0
+ );
+ (void)state;
+}
diff --git a/src/boost/libs/stacktrace/build/has_windbg.cpp b/src/boost/libs/stacktrace/build/has_windbg.cpp
new file mode 100644
index 000000000..da016482c
--- /dev/null
+++ b/src/boost/libs/stacktrace/build/has_windbg.cpp
@@ -0,0 +1,13 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <cstring>
+#include <windows.h>
+#include "dbgeng.h"
+
+int main() {
+ ::CoInitializeEx(0, COINIT_MULTITHREADED);
+}
diff --git a/src/boost/libs/stacktrace/build/has_windbg_cached.cpp b/src/boost/libs/stacktrace/build/has_windbg_cached.cpp
new file mode 100644
index 000000000..163ce98e7
--- /dev/null
+++ b/src/boost/libs/stacktrace/build/has_windbg_cached.cpp
@@ -0,0 +1,28 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <boost/config.hpp>
+
+#include <string>
+#include <cstring>
+#include <windows.h>
+#include "dbgeng.h"
+
+#ifdef BOOST_NO_CXX11_THREAD_LOCAL
+# error Your compiler does not support C++11 thread_local storage. It`s impossible to build with BOOST_STACKTRACE_USE_WINDBG_CACHED.
+#endif
+
+int foo() {
+ static thread_local std::string i = std::string();
+
+ return static_cast<int>(i.size());
+}
+
+int main() {
+ ::CoInitializeEx(0, COINIT_MULTITHREADED);
+
+ return foo();
+}
diff --git a/src/boost/libs/stacktrace/example/assert_handler.cpp b/src/boost/libs/stacktrace/example/assert_handler.cpp
new file mode 100644
index 000000000..63a056260
--- /dev/null
+++ b/src/boost/libs/stacktrace/example/assert_handler.cpp
@@ -0,0 +1,55 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_ENABLE_ASSERT_HANDLER
+
+#include <cstdlib> // std::exit
+#include <boost/array.hpp>
+BOOST_NOINLINE void foo(int i);
+BOOST_NOINLINE void bar(int i);
+
+BOOST_NOINLINE void bar(int i) {
+ boost::array<int, 5> a = {{101, 100, 123, 23, 32}};
+ if (i >= 0) {
+ foo(a[i]);
+ } else {
+ std::exit(1);
+ }
+}
+
+BOOST_NOINLINE void foo(int i) {
+ bar(--i);
+}
+
+//[getting_started_assert_handlers
+
+// 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::exit(0); /*->*/
+ /*=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
+//]
+
+
+int main() {
+ foo(5);
+
+ return 2;
+}
+
+
diff --git a/src/boost/libs/stacktrace/example/debug_function.cpp b/src/boost/libs/stacktrace/example/debug_function.cpp
new file mode 100644
index 000000000..7c44d78e4
--- /dev/null
+++ b/src/boost/libs/stacktrace/example/debug_function.cpp
@@ -0,0 +1,33 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+//[getting_started_debug_function
+#include <signal.h> // ::signal
+#include <boost/stacktrace/frame.hpp>
+#include <iostream> // std::cerr
+#include <cstdlib> // std::exit
+
+void print_signal_handler_and_exit() {
+ typedef void(*function_t)(int);
+
+ function_t old_signal_function = ::signal(SIGSEGV, SIG_DFL);
+ boost::stacktrace::frame f(old_signal_function);
+ std::cout << f << std::endl;
+ std::exit(0);
+}
+//]
+
+
+void my_signal_handler(int /*signum*/) {
+ std::exit(1);
+}
+
+int main() {
+ ::signal(SIGSEGV, &my_signal_handler);
+ print_signal_handler_and_exit();
+}
+
+
diff --git a/src/boost/libs/stacktrace/example/terminate_handler.cpp b/src/boost/libs/stacktrace/example/terminate_handler.cpp
new file mode 100644
index 000000000..4f07777c1
--- /dev/null
+++ b/src/boost/libs/stacktrace/example/terminate_handler.cpp
@@ -0,0 +1,326 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <boost/array.hpp>
+BOOST_NOINLINE void foo(int i);
+BOOST_NOINLINE void bar(int i);
+
+BOOST_NOINLINE void bar(int i) {
+ boost::array<int, 5> a = {{-1, -231, -123, -23, -32}};
+ if (i >= 0) {
+ foo(a[i]);
+ } else {
+ std::terminate();
+ }
+}
+
+BOOST_NOINLINE void foo(int i) {
+ bar(--i);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//[getting_started_terminate_handlers
+
+#include <signal.h> // ::signal, ::raise
+#include <boost/stacktrace.hpp>
+
+void my_signal_handler(int signum) {
+ ::signal(signum, SIG_DFL);
+ boost::stacktrace::safe_dump_to("./backtrace.dump");
+ ::raise(SIGABRT);
+}
+//]
+
+void setup_handlers() {
+//[getting_started_setup_handlers
+ ::signal(SIGSEGV, &my_signal_handler);
+ ::signal(SIGABRT, &my_signal_handler);
+//]
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+BOOST_CONSTEXPR_OR_CONST std::size_t shared_memory_size = 4096 * 8;
+
+//[getting_started_terminate_handlers_shmem
+#include <boost/stacktrace.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+
+boost::interprocess::shared_memory_object g_shm; // inited at program start
+boost::interprocess::mapped_region g_region; // inited at program start
+
+
+void my_signal_handler2(int signum) {
+ ::signal(signum, SIG_DFL);
+ void** f = static_cast<void**>(g_region.get_address());
+ *f = reinterpret_cast<void*>(1); // Setting flag that shared memory now constains stacktrace.
+ boost::stacktrace::safe_dump_to(f + 1, g_region.get_size() - sizeof(void*));
+
+ ::raise(SIGABRT);
+}
+//]
+
+#include <iostream> // std::cerr
+#include <fstream> // std::ifstream
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+
+
+inline void copy_and_run(const char* exec_name, char param, bool not_null) {
+ std::cout << "Running with param " << param << std::endl;
+ boost::filesystem::path command = exec_name;
+ command = command.parent_path() / (command.stem().string() + param + command.extension().string());
+ boost::filesystem::copy_file(exec_name, command, boost::filesystem::copy_option::overwrite_if_exists);
+
+ boost::filesystem::path command_args = command;
+ command_args += ' ';
+ command_args += param;
+ const int ret = std::system(command_args.string().c_str());
+
+ std::cout << "End Running with param " << param << "; ret code is " << ret << std::endl;
+ boost::system::error_code ignore;
+ boost::filesystem::remove(command, ignore);
+ if (not_null && !ret) {
+ std::exit(97);
+ } else if (!not_null && ret) {
+ std::exit(ret);
+ }
+}
+
+int run_1(const char* /*argv*/[]) {
+ setup_handlers();
+ foo(5);
+ return 11;
+}
+
+int run_2(const char* argv[]) {
+ if (!boost::filesystem::exists("./backtrace.dump")) {
+ if (std::string(argv[0]).find("noop") == std::string::npos) {
+ return 21;
+ }
+
+ boost::stacktrace::stacktrace st = boost::stacktrace::stacktrace::from_dump(std::cin);
+ if (st) {
+ return 22;
+ }
+ return 0;
+ }
+
+//[getting_started_on_program_restart
+ if (boost::filesystem::exists("./backtrace.dump")) {
+ // there is a backtrace
+ std::ifstream ifs("./backtrace.dump");
+
+ boost::stacktrace::stacktrace st = boost::stacktrace::stacktrace::from_dump(ifs);
+ std::cout << "Previous run crashed:\n" << st << std::endl; /*<-*/
+
+ if (!st) {
+ return 23;
+ } /*->*/
+
+ // cleaning up
+ ifs.close();
+ boost::filesystem::remove("./backtrace.dump");
+ }
+//]
+
+ return 0;
+}
+
+
+int run_3(const char* /*argv*/[]) {
+ using namespace boost::interprocess;
+ {
+ shared_memory_object shm_obj(open_or_create, "shared_memory", read_write);
+ shm_obj.swap(g_shm);
+ }
+ g_shm.truncate(shared_memory_size);
+
+ {
+ mapped_region m(g_shm, read_write, 0, shared_memory_size);
+ m.swap(g_region);
+ }
+ void** f = static_cast<void**>(g_region.get_address());
+ *f = 0;
+
+ ::signal(SIGSEGV, &my_signal_handler2);
+ ::signal(SIGABRT, &my_signal_handler2);
+ foo(5);
+ return 31;
+}
+
+int run_4(const char* argv[]) {
+ using namespace boost::interprocess;
+ {
+ shared_memory_object shm_obj(open_only, "shared_memory", read_write);
+ shm_obj.swap(g_shm);
+ }
+
+ {
+ mapped_region m(g_shm, read_write, 0, shared_memory_size);
+ m.swap(g_region);
+ }
+
+//[getting_started_on_program_restart_shmem
+ void** f = static_cast<void**>(g_region.get_address());
+ if (*f) { // Checking if memory constains stacktrace.
+ boost::stacktrace::stacktrace st
+ = boost::stacktrace::stacktrace::from_dump(f + 1, g_region.get_size() - sizeof(bool));
+
+ std::cout << "Previous run crashed and left trace in shared memory:\n" << st << std::endl;
+ *f = 0; /*<-*/
+ shared_memory_object::remove("shared_memory");
+ if (std::string(argv[0]).find("noop") == std::string::npos) {
+ if (!st) {
+ return 43;
+ }
+ } else {
+ if (st) {
+ return 44;
+ }
+ }
+ } else {
+ return 42; /*->*/
+ }
+//]
+
+
+ return 0;
+}
+
+#include <sstream>
+
+int test_inplace() {
+ const bool is_noop = !boost::stacktrace::stacktrace();
+
+ {
+ // This is very dependent on compiler and link flags. No sane way to make it work, because:
+ // * BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
+ // * BOOST_FORCEINLINE could be ignored by GCC depending on the std::vector default constructor length.
+ const std::size_t frames_ss1 = boost::stacktrace::safe_dump_to("./backtrace2.dump");
+ boost::stacktrace::stacktrace ss2;
+ std::ifstream ifs("./backtrace2.dump");
+ boost::stacktrace::stacktrace ss1 = boost::stacktrace::stacktrace::from_dump(ifs);
+ ifs.close();
+ boost::filesystem::remove("./backtrace2.dump");
+
+ if (ss1.size() + 1 != frames_ss1 || ss2.size() != ss1.size()) {
+ std::cerr << "51: Stacktraces differ. Dumped size == " << frames_ss1 << ".\n" << ss1 << "\n vs \n" << ss2 << '\n';
+ } else if (ss1.size() > 1 && ss1[1].name() != ss2[1].name()) {
+ std::cerr << "52: Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
+ }
+ }
+
+ {
+ // This is very dependent on compiler and link flags. No sane way to make it work, because:
+ // * BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
+ // * BOOST_FORCEINLINE could be ignored by GCC depending on the std::vector default constructor length.
+ void* data[1024];
+ const std::size_t frames_ss1 = boost::stacktrace::safe_dump_to(data, sizeof(data));
+ boost::stacktrace::stacktrace ss2;
+ boost::stacktrace::stacktrace ss1 = boost::stacktrace::stacktrace::from_dump(data, sizeof(data));
+
+ if (ss1.size() + 1 != frames_ss1 || ss1.size() != ss2.size()) {
+ std::cerr << "53: Stacktraces differ. Dumped size == " << frames_ss1 << ".\n" << ss1 << "\n vs \n" << ss2 << '\n';
+ } else if (ss1.size() > 1 && ss1[1].name() != ss2[1].name()) {
+ std::cerr << "54: Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
+ }
+ }
+
+ {
+ void* data[1024];
+ boost::stacktrace::safe_dump_to(1024, data, sizeof(data));
+ if (boost::stacktrace::stacktrace::from_dump(data, sizeof(data))) {
+ std::cerr << "Stacktrace not empty!\n";
+ return 55;
+ }
+ }
+
+ {
+ void* data[1024];
+ boost::stacktrace::safe_dump_to(1, data, sizeof(data));
+ if (!is_noop && !boost::stacktrace::stacktrace::from_dump(data, sizeof(data))) {
+ std::cerr << "Stacktrace empty!\n";
+ return 56;
+ }
+ const std::size_t size_1_skipped = boost::stacktrace::stacktrace::from_dump(data, sizeof(data)).size();
+ boost::stacktrace::safe_dump_to(0, data, sizeof(data));
+ const std::size_t size_0_skipped = boost::stacktrace::stacktrace::from_dump(data, sizeof(data)).size();
+
+ if (!is_noop && (size_1_skipped + 1 != size_0_skipped)) {
+ std::cerr << "failed to skip 1 frame!\n";
+ return 57;
+ }
+ }
+
+ {
+ boost::stacktrace::safe_dump_to(0, 1, "./backtrace3.dump");
+ std::ifstream ifs("./backtrace3.dump");
+ boost::stacktrace::stacktrace ss1 = boost::stacktrace::stacktrace::from_dump(ifs);
+ ifs.close();
+
+ boost::stacktrace::safe_dump_to(1, 1, "./backtrace3.dump");
+ ifs.open("./backtrace3.dump");
+ boost::stacktrace::stacktrace ss2 = boost::stacktrace::stacktrace::from_dump(ifs);
+ ifs.close();
+
+ boost::filesystem::remove("./backtrace3.dump");
+
+#ifdef BOOST_WINDOWS
+ // `ss2` could be empty on some combinations of Windows+MSVC.
+ if (!ss2) {
+ return 0;
+ }
+#endif
+
+ if (ss1.size() != ss2.size()) {
+ std::cerr << "Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
+ return 58;
+ }
+
+ if (!is_noop && ss1.size() != 1) {
+ std::cerr << "Stacktraces does not have size 1:\n" << ss1 << '\n';
+ return 59;
+ }
+
+ if (ss1 && ss1[0].address() == ss2[0].address()) {
+ std::cerr << "Stacktraces must differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
+ return 60;
+ }
+ }
+
+ return 0;
+}
+
+
+int main(int argc, const char* argv[]) {
+ if (argc < 2) {
+#ifndef BOOST_WINDOWS
+ // We are copying files to make sure that stacktrace printing works independently from executable name
+ copy_and_run(argv[0], '1', true);
+ copy_and_run(argv[0], '2', false);
+
+ // There are some issues with async-safety of shared memory writes on Windows.
+ copy_and_run(argv[0], '3', true);
+ copy_and_run(argv[0], '4', false);
+#endif
+
+ return test_inplace();
+ }
+
+ switch (argv[1][0]) {
+ case '1': return run_1(argv);
+ case '2': return run_2(argv);
+ case '3': return run_3(argv);
+ case '4': return run_4(argv);
+ }
+
+ return 404;
+}
+
+
diff --git a/src/boost/libs/stacktrace/example/throwing_st.cpp b/src/boost/libs/stacktrace/example/throwing_st.cpp
new file mode 100644
index 000000000..ecf67909d
--- /dev/null
+++ b/src/boost/libs/stacktrace/example/throwing_st.cpp
@@ -0,0 +1,78 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <boost/config.hpp>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//[getting_started_class_traced
+#include <boost/stacktrace.hpp>
+#include <boost/exception/all.hpp>
+
+typedef boost::error_info<struct tag_stacktrace, boost::stacktrace::stacktrace> traced;
+//]
+
+//[getting_started_class_with_trace
+template <class E>
+void throw_with_trace(const E& e) {
+ throw boost::enable_error_info(e)
+ << traced(boost::stacktrace::stacktrace());
+}
+//]
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+BOOST_NOINLINE void oops(int i);
+BOOST_NOINLINE void foo(int i);
+BOOST_NOINLINE void bar(int i);
+
+#include <stdexcept>
+BOOST_NOINLINE void oops(int i) {
+ //[getting_started_throwing_with_trace
+ if (i >= 4)
+ throw_with_trace(std::out_of_range("'i' must be less than 4 in oops()"));
+ if (i <= 0)
+ throw_with_trace(std::logic_error("'i' must be greater than zero in oops()"));
+ //]
+ foo(i);
+ std::exit(1);
+}
+
+#include <boost/array.hpp>
+BOOST_NOINLINE void bar(int i) {
+ boost::array<int, 5> a = {{0, 0, 0, 0, 0}};
+ if (i < 5) {
+ if (i >= 0) {
+ foo(a[i]);
+ } else {
+ oops(i);
+ }
+ }
+ std::exit(2);
+}
+
+BOOST_NOINLINE void foo(int i) {
+ bar(--i);
+}
+
+#include <iostream>
+int main() {
+
+ //[getting_started_catching_trace
+ try {
+ foo(5); // testing assert handler
+ } catch (const std::exception& e) {
+ std::cerr << e.what() << '\n';
+ const boost::stacktrace::stacktrace* st = boost::get_error_info<traced>(e);
+ if (st) {
+ std::cerr << *st << '\n'; /*<-*/ return 0; /*->*/
+ } /*<-*/ return 3; /*->*/
+ }
+ //]
+
+ return 5;
+}
+
diff --git a/src/boost/libs/stacktrace/example/trace_addresses.cpp b/src/boost/libs/stacktrace/example/trace_addresses.cpp
new file mode 100644
index 000000000..dedec1ef3
--- /dev/null
+++ b/src/boost/libs/stacktrace/example/trace_addresses.cpp
@@ -0,0 +1,63 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <boost/config.hpp>
+
+#ifdef BOOST_NO_CXX11_RANGE_BASED_FOR
+#include <boost/stacktrace.hpp>
+#include <iostream> // std::cout
+
+namespace bs = boost::stacktrace;
+void dump_compact(const bs::stacktrace& st) {
+ for (unsigned i = 0; i < st.size(); ++i) {
+ bs::frame frame = st[i];
+ std::cout << frame.address() << ',';
+ }
+
+ std::cout << std::endl;
+}
+#else
+//[getting_started_trace_addresses
+#include <boost/stacktrace.hpp>
+#include <iostream> // std::cout
+
+namespace bs = boost::stacktrace;
+void dump_compact(const bs::stacktrace& st) {
+ for (bs::frame frame: st) {
+ std::cout << frame.address() << ',';
+ }
+
+ std::cout << std::endl;
+}
+//]
+#endif
+
+BOOST_NOINLINE boost::stacktrace::stacktrace rec1(int i);
+BOOST_NOINLINE boost::stacktrace::stacktrace rec2(int i);
+
+BOOST_NOINLINE boost::stacktrace::stacktrace rec1(int i) {
+ if (i < 5) {
+ if (!i) return boost::stacktrace::stacktrace();
+ return rec2(--i);
+ }
+
+ return rec2(i - 2);
+}
+
+BOOST_NOINLINE boost::stacktrace::stacktrace rec2(int i) {
+ if (i < 5) {
+ if (!i) return boost::stacktrace::stacktrace();
+ return rec2(--i);
+ }
+
+ return rec2(i - 2);
+}
+
+int main() {
+ dump_compact(rec1(8));
+}
+
+
diff --git a/src/boost/libs/stacktrace/example/user_config.cpp b/src/boost/libs/stacktrace/example/user_config.cpp
new file mode 100644
index 000000000..dc9354674
--- /dev/null
+++ b/src/boost/libs/stacktrace/example/user_config.cpp
@@ -0,0 +1,38 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_USER_CONFIG <libs/stacktrace/example/user_config.hpp>
+
+#include <boost/array.hpp>
+#include <exception> // std::set_terminate, std::abort
+#include <boost/stacktrace.hpp>
+#include <iostream> // std::cerr
+BOOST_NOINLINE void foo(int i);
+BOOST_NOINLINE void bar(int i);
+
+BOOST_NOINLINE void bar(int i) {
+ boost::array<int, 5> a = {{-1, -231, -123, -23, -32}};
+ if (i >= 0) {
+ foo(a[i]);
+ } else {
+ std::cerr << "Terminate called:\n" << boost::stacktrace::stacktrace() << '\n';
+ std::exit(0);
+ }
+}
+
+BOOST_NOINLINE void foo(int i) {
+ bar(--i);
+}
+
+int main() {
+ foo(5);
+
+ return 2;
+}
+
+
+
+
diff --git a/src/boost/libs/stacktrace/example/user_config.hpp b/src/boost/libs/stacktrace/example/user_config.hpp
new file mode 100644
index 000000000..d9daf25b3
--- /dev/null
+++ b/src/boost/libs/stacktrace/example/user_config.hpp
@@ -0,0 +1,58 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+
+//[getting_started_user_config
+#ifndef USER_CONFIG_HPP
+#define USER_CONFIG_HPP
+
+#include <boost/stacktrace/stacktrace_fwd.hpp>
+
+#include <iosfwd>
+
+namespace boost { namespace stacktrace {
+
+template <class CharT, class TraitsT, class Allocator>
+std::basic_ostream<CharT, TraitsT>& do_stream_st(std::basic_ostream<CharT, TraitsT>& os, const basic_stacktrace<Allocator>& bt);
+
+template <class CharT, class TraitsT>
+std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const stacktrace& bt) {
+ return do_stream_st(os, bt);
+}
+
+}} // namespace boost::stacktrace
+#endif // USER_CONFIG_HPP
+//]
+
+#ifndef USER_CONFIG2_HPP
+#define USER_CONFIG2_HPP
+
+#include <ios> // std::streamsize
+
+//[getting_started_user_config_impl
+namespace boost { namespace stacktrace {
+
+template <class CharT, class TraitsT, class Allocator>
+std::basic_ostream<CharT, TraitsT>& do_stream_st(std::basic_ostream<CharT, TraitsT>& os, const basic_stacktrace<Allocator>& bt) {
+ const std::streamsize w = os.width();
+ const std::size_t frames = bt.size();
+ for (std::size_t i = 0; i < frames; ++i) {
+ os.width(2);
+ os << i;
+ os.width(w);
+ os << "# ";
+ os << bt[i].name();
+ os << '\n';
+ }
+
+ return os;
+}
+
+}} // namespace boost::stacktrace
+//]
+
+#endif // USER_CONFIG2_HPP
+
diff --git a/src/boost/libs/stacktrace/index.html b/src/boost/libs/stacktrace/index.html
new file mode 100644
index 000000000..ee7ddb8e2
--- /dev/null
+++ b/src/boost/libs/stacktrace/index.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+ Copyright (c) 2014-2019 Antony Polukhin
+ antoshkka at gmail dot com
+
+ Distributed under the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt
+ or copy at http://boost.org/LICENSE_1_0.txt)
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<meta http-equiv="refresh" content="0; url=../../doc/html/stacktrace.html">
+<title>Boost.Stacktrace</title>
+<style>
+ body {
+ background: #fff;
+ color: #000;
+ }
+ a {
+ color: #00f;
+ text-decoration: none;
+ }
+</style>
+</head>
+<body>
+ <p>
+ Automatic redirection failed, please go to
+ <a href="../../doc/html/stacktrace.html">../../doc/html/stacktrace.html</a>
+ </p>
+ <p>
+ &copy; 2014-2019 Antony Polukhin
+ </p>
+</body>
+</html>
diff --git a/src/boost/libs/stacktrace/meta/libraries.json b/src/boost/libs/stacktrace/meta/libraries.json
new file mode 100644
index 000000000..7f7a8cd73
--- /dev/null
+++ b/src/boost/libs/stacktrace/meta/libraries.json
@@ -0,0 +1,15 @@
+{
+ "key": "stacktrace",
+ "name": "Stacktrace",
+ "authors": [
+ "Antony Polukhin"
+ ],
+ "maintainers": [
+ "Antony Polukhin <antoshkka -at- gmail.com>"
+ ],
+ "description": "Gather, store, copy and print backtraces.",
+ "std": [ "proposal" ],
+ "category": [
+ "System", "Correctness"
+ ]
+}
diff --git a/src/boost/libs/stacktrace/src/addr2line.cpp b/src/boost/libs/stacktrace/src/addr2line.cpp
new file mode 100644
index 000000000..36964b8b4
--- /dev/null
+++ b/src/boost/libs/stacktrace/src/addr2line.cpp
@@ -0,0 +1,16 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
+#define BOOST_STACKTRACE_USE_ADDR2LINE
+#define BOOST_STACKTRACE_LINK
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <boost/stacktrace/detail/frame_unwind.ipp>
+#include <boost/stacktrace/safe_dump_to.hpp>
diff --git a/src/boost/libs/stacktrace/src/backtrace.cpp b/src/boost/libs/stacktrace/src/backtrace.cpp
new file mode 100644
index 000000000..4c881f21b
--- /dev/null
+++ b/src/boost/libs/stacktrace/src/backtrace.cpp
@@ -0,0 +1,16 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
+#define BOOST_STACKTRACE_USE_BACKTRACE
+#define BOOST_STACKTRACE_LINK
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <boost/stacktrace/detail/frame_unwind.ipp>
+#include <boost/stacktrace/safe_dump_to.hpp>
diff --git a/src/boost/libs/stacktrace/src/basic.cpp b/src/boost/libs/stacktrace/src/basic.cpp
new file mode 100644
index 000000000..7e1cfffb6
--- /dev/null
+++ b/src/boost/libs/stacktrace/src/basic.cpp
@@ -0,0 +1,15 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
+#define BOOST_STACKTRACE_LINK
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <boost/stacktrace/detail/frame_unwind.ipp>
+#include <boost/stacktrace/safe_dump_to.hpp>
diff --git a/src/boost/libs/stacktrace/src/noop.cpp b/src/boost/libs/stacktrace/src/noop.cpp
new file mode 100644
index 000000000..a6a1e97f7
--- /dev/null
+++ b/src/boost/libs/stacktrace/src/noop.cpp
@@ -0,0 +1,11 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
+#define BOOST_STACKTRACE_LINK
+#define BOOST_STACKTRACE_USE_NOOP
+#include <boost/stacktrace/detail/frame_noop.ipp>
+#include <boost/stacktrace/detail/safe_dump_noop.ipp>
diff --git a/src/boost/libs/stacktrace/src/windbg.cpp b/src/boost/libs/stacktrace/src/windbg.cpp
new file mode 100644
index 000000000..b58b3ea0f
--- /dev/null
+++ b/src/boost/libs/stacktrace/src/windbg.cpp
@@ -0,0 +1,10 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
+#define BOOST_STACKTRACE_LINK
+#include <boost/stacktrace/detail/frame_msvc.ipp>
+#include <boost/stacktrace/safe_dump_to.hpp>
diff --git a/src/boost/libs/stacktrace/src/windbg_cached.cpp b/src/boost/libs/stacktrace/src/windbg_cached.cpp
new file mode 100644
index 000000000..3ab2b9b4f
--- /dev/null
+++ b/src/boost/libs/stacktrace/src/windbg_cached.cpp
@@ -0,0 +1,11 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
+#define BOOST_STACKTRACE_LINK
+#define BOOST_STACKTRACE_USE_WINDBG_CACHED
+#include <boost/stacktrace/detail/frame_msvc.ipp>
+#include <boost/stacktrace/safe_dump_to.hpp>
diff --git a/src/boost/libs/stacktrace/test/Jamfile.v2 b/src/boost/libs/stacktrace/test/Jamfile.v2
new file mode 100644
index 000000000..48576ddb9
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/Jamfile.v2
@@ -0,0 +1,245 @@
+# Copyright (C) 2016-2019, Antony Polukhin.
+#
+# Use, modification and distribution is 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)
+#
+
+import ../../config/checks/config : requires ;
+
+lib dl : : <link>shared ;
+lib gcc_s ;
+lib rt ;
+lib Dbgeng ;
+lib ole32 ;
+
+local LIBBACKTRACE_PATH = [ modules.peek : LIBBACKTRACE_PATH ] ;
+lib backtrace
+ :
+ : <search>$(LIBBACKTRACE_PATH)/lib <link>static
+ :
+ : <include>$(LIBBACKTRACE_PATH)/include
+ ;
+
+
+project
+ : requirements
+ <toolset>msvc:<asynch-exceptions>on
+ <toolset>intel:<cxxflags>-wd2196
+ <target-os>linux:<linkflags>-lpthread
+ <warnings>all
+ <test-info>always_show_run_output
+ <visibility>hidden
+ ;
+
+local FORCE_SYMBOL_EXPORT = <target-os>freebsd:<linkflags>"-rdynamic" <target-os>solaris:<linkflags>"-Bdynamic" <target-os>aix:<linkflags>"-rdynamic"
+ <target-os>qnxnto,<toolset>qcc:<linkflags>"-Bdynamic" <target-os>qnxnto,<toolset>gcc:<linkflags>"-rdynamic"
+ <target-os>android:<linkflags>"-rdynamic" <target-os>linux:<linkflags>"-rdynamic" <target-os>darwin,<toolset>gcc:<linkflags>"-dynamic"
+ <target-os>darwin,<toolset>clang:<linkflags>"-rdynamic" <target-os>iphone:<linkflags>"-rdynamic"
+ <define>BOOST_STACKTRACE_TEST_EXPORTS_TABLE_USAGE ;
+
+local BT_DEPS = <target-os>linux:<library>dl <library>backtrace [ check-target-builds ../build//libbacktrace : : <build>no ] ;
+local AD2L_DEPS = <target-os>linux:<library>dl [ check-target-builds ../build//addr2line : : <build>no ]
+ <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL # Some old versions of addr2line may not produce readable names for a modern compilers
+ ;
+local WIND_DEPS = <library>Dbgeng <library>ole32 [ check-target-builds ../build//WinDbg : : <build>no ] ;
+local WICA_DEPS = <library>Dbgeng <library>ole32 [ check-target-builds ../build//WinDbgCached : : <build>no ] ;
+local NOOP_DEPS = ;
+local BASIC_DEPS = <target-os>linux:<library>dl [ check-target-builds ../build//WinDbg : <build>no ] ;
+
+local LINKSHARED_BT = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_backtrace $(BT_DEPS) ;
+local LINKSHARED_AD2L = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_addr2line $(AD2L_DEPS) ;
+local LINKSHARED_WIND = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_windbg $(WIND_DEPS) ;
+local LINKSHARED_WIND_CACHED = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_windbg_cached $(WICA_DEPS) ;
+local LINKSHARED_NOOP = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_noop $(NOOP_DEPS) ;
+local LINKSHARED_BASIC = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_basic $(BASIC_DEPS) $(FORCE_SYMBOL_EXPORT) ;
+
+# Libs with debug symbols
+lib test_impl_lib_backtrace : test_impl.cpp : <debug-symbols>on $(LINKSHARED_BT) ;
+lib test_impl_lib_addr2line : test_impl.cpp : <debug-symbols>on $(LINKSHARED_AD2L) ;
+lib test_impl_lib_windbg : test_impl.cpp : <debug-symbols>on $(LINKSHARED_WIND) ;
+lib test_impl_lib_windbg_cached : test_impl.cpp : <debug-symbols>on $(LINKSHARED_WIND_CACHED) ;
+lib test_impl_lib_noop : test_impl.cpp : <debug-symbols>on $(LINKSHARED_NOOP) ;
+
+obj test_impl_nohide-obj : test_impl.cpp : <debug-symbols>on $(LINKSHARED_BASIC) ;
+lib test_impl_lib_basic : test_impl_nohide-obj : <debug-symbols>on $(LINKSHARED_BASIC) ;
+
+
+# Libs without debug symbols
+lib test_impl_lib_backtrace_no_dbg : test_impl.cpp : <debug-symbols>off $(LINKSHARED_BT) ;
+lib test_impl_lib_addr2line_no_dbg : test_impl.cpp : <debug-symbols>off $(LINKSHARED_AD2L) ;
+lib test_impl_lib_windbg_no_dbg : test_impl.cpp : <debug-symbols>off $(LINKSHARED_WIND) ;
+lib test_impl_lib_windbg_cached_no_dbg : test_impl.cpp : <debug-symbols>off $(LINKSHARED_WIND_CACHED) ;
+lib test_impl_lib_noop_no_dbg : test_impl.cpp : <debug-symbols>off $(LINKSHARED_NOOP) ;
+
+obj test_impl_nohide_no_dbg-obj : test_impl.cpp : <debug-symbols>off $(LINKSHARED_BASIC) ;
+lib test_impl_lib_basic_no_dbg : test_impl_nohide_no_dbg-obj : <debug-symbols>off $(LINKSHARED_BASIC) ;
+
+
+test-suite stacktrace_tests
+ :
+
+ # Header only tests with debug symbols
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_BACKTRACE $(BT_DEPS) : backtrace_ho ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_ADDR2LINE $(AD2L_DEPS) : addr2line_ho ]
+ [ run test_noop.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_NOOP $(NOOP_DEPS) : noop_ho ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>on $(WIND_DEPS) : windbg_ho ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_WINDBG_CACHED $(WICA_DEPS) : windbg_cached_ho ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>on $(FORCE_SYMBOL_EXPORT) $(BASIC_DEPS) : basic_ho ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL $(BASIC_DEPS) : basic_ho_empty ]
+
+ # Test with shared linked implementations with debug symbols
+ [ run test.cpp : : : <debug-symbols>on <library>.//test_impl_lib_backtrace $(LINKSHARED_BT) : backtrace_lib ]
+ [ run test.cpp : : : <debug-symbols>on <library>.//test_impl_lib_addr2line $(LINKSHARED_AD2L) : addr2line_lib ]
+ [ run test.cpp : : : <debug-symbols>on <library>.//test_impl_lib_windbg $(LINKSHARED_WIND) : windbg_lib ]
+ [ run test.cpp : : : <debug-symbols>on <library>.//test_impl_lib_windbg_cached $(LINKSHARED_WIND_CACHED) : windbg_cached_lib ]
+ [ run test_noop.cpp : : : <debug-symbols>on <library>.//test_impl_lib_noop $(LINKSHARED_NOOP) : noop_lib ]
+ [ run test.cpp : : : <debug-symbols>on <library>.//test_impl_lib_basic $(LINKSHARED_BASIC) : basic_lib ]
+
+ # Thread safety with debug symbols
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>on <library>/boost/thread//boost_thread <library>/boost/timer//boost_timer <library>.//test_impl_lib_backtrace $(LINKSHARED_BT)
+ : backtrace_lib_threaded ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>on <library>/boost/thread//boost_thread <library>/boost/timer//boost_timer <library>.//test_impl_lib_windbg $(LINKSHARED_WIND)
+ : windbg_lib_threaded ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>on <library>/boost/thread//boost_thread <library>/boost/timer//boost_timer <library>.//test_impl_lib_windbg_cached $(LINKSHARED_WIND_CACHED)
+ : windbg_cached_lib_threaded ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>on <library>/boost/thread//boost_thread <library>/boost/timer//boost_timer <library>.//test_impl_lib_basic $(LINKSHARED_BASIC)
+ : basic_lib_threaded ]
+
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>on <library>/boost/thread//boost_thread <library>/boost/timer//boost_timer <library>.//test_impl_lib_windbg
+ $(LINKSHARED_WIND) <define>BOOST_STACKTRACE_TEST_COM_PREINIT_MT
+ : windbg_lib_threaded_com_mt ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>on <library>/boost/thread//boost_thread <library>/boost/timer//boost_timer <library>.//test_impl_lib_windbg_cached
+ $(LINKSHARED_WIND_CACHED) <define>BOOST_STACKTRACE_TEST_COM_PREINIT_ST
+ : windbg_cached_lib_threaded_com_st ]
+
+ ##### Tests with disabled debug symbols #####
+
+ # Header only tests without debug symbols
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>off <define>BOOST_STACKTRACE_USE_BACKTRACE $(FORCE_SYMBOL_EXPORT) $(BT_DEPS) : backtrace_ho_no_dbg ]
+ [ run test_noop.cpp test_impl.cpp : : : <debug-symbols>off <define>BOOST_STACKTRACE_USE_NOOP $(NOOP_DEPS) : noop_ho_no_dbg ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>off <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL $(WIND_DEPS) : windbg_ho_no_dbg ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>off <define>BOOST_STACKTRACE_USE_WINDBG_CACHED <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL $(WICA_DEPS) : windbg_cached_ho_no_dbg ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>off $(FORCE_SYMBOL_EXPORT) $(BASIC_DEPS) : basic_ho_no_dbg ]
+ [ run test.cpp test_impl.cpp : : : <debug-symbols>off <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL $(BASIC_DEPS) : basic_ho_no_dbg_empty ]
+ [ run test.cpp test_impl.cpp
+ : : : <debug-symbols>off <define>BOOST_STACKTRACE_USE_ADDR2LINE <define>BOOST_STACKTRACE_ADDR2LINE_LOCATION="/usr/bin/addr2line" $(AD2L_DEPS)
+ : addr2line_ho_no_dbg ]
+
+ # Test with shared linked implementations without debug symbols
+ [ run test.cpp : : : <debug-symbols>off <library>.//test_impl_lib_backtrace_no_dbg $(LINKSHARED_BT) $(FORCE_SYMBOL_EXPORT) : backtrace_lib_no_dbg ]
+ [ run test.cpp : : : <debug-symbols>off <library>.//test_impl_lib_addr2line_no_dbg $(LINKSHARED_AD2L) : addr2line_lib_no_dbg ]
+ [ run test.cpp : : : <debug-symbols>off <library>.//test_impl_lib_windbg_no_dbg $(LINKSHARED_WIND) <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL : windbg_lib_no_dbg ]
+ [ run test.cpp : : : <debug-symbols>off <library>.//test_impl_lib_windbg_cached_no_dbg $(LINKSHARED_WIND_CACHED) <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL : windbg_cached_lib_no_dbg ]
+ [ run test_noop.cpp : : : <debug-symbols>off <library>.//test_impl_lib_noop_no_dbg $(LINKSHARED_NOOP) : noop_lib_no_dbg ]
+ [ run test.cpp : : : <debug-symbols>off <library>.//test_impl_lib_basic_no_dbg $(LINKSHARED_BASIC) : basic_lib_no_dbg ]
+
+ # Thread safety without debug symbols
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>off
+ <library>/boost/thread//boost_thread
+ <library>/boost/timer//boost_timer
+ <library>.//test_impl_lib_backtrace_no_dbg
+ $(LINKSHARED_BT)
+ : backtrace_lib_no_dbg_threaded ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>off
+ <library>/boost/thread//boost_thread
+ <library>/boost/timer//boost_timer
+ <library>.//test_impl_lib_windbg_no_dbg
+ $(LINKSHARED_WIND)
+ : windbg_lib_no_dbg_threaded ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>off
+ <library>/boost/thread//boost_thread
+ <library>/boost/timer//boost_timer
+ <library>.//test_impl_lib_windbg_cached_no_dbg
+ $(LINKSHARED_WIND_CACHED)
+ : windbg_cached_lib_no_dbg_threaded ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>off
+ <library>/boost/thread//boost_thread
+ <library>/boost/timer//boost_timer
+ <library>.//test_impl_lib_basic_no_dbg
+ $(LINKSHARED_BASIC)
+ : basic_lib_no_dbg_threaded ]
+
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>off
+ <library>/boost/thread//boost_thread
+ <library>/boost/timer//boost_timer
+ <library>.//test_impl_lib_windbg
+ $(LINKSHARED_WIND)
+ <define>BOOST_STACKTRACE_TEST_COM_PREINIT_MT
+ : windbg_lib_threaded_com_mt ]
+ [ run thread_safety_checking.cpp
+ : : : <debug-symbols>off
+ <library>/boost/thread//boost_thread
+ <library>/boost/timer//boost_timer
+ <library>.//test_impl_lib_windbg_cached
+ $(LINKSHARED_WIND_CACHED)
+ <define>BOOST_STACKTRACE_TEST_COM_PREINIT_ST
+ : windbg_cached_lib_threaded_com_st ]
+
+ [ run test_void_ptr_cast.cpp ]
+ [ run test_num_conv.cpp ]
+ ;
+
+# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite.
+for local p in [ glob ../example/*.cpp ]
+{
+ local target_name = $(p[1]:B) ;
+ local additional_dependency = ;
+ if $(target_name) = "terminate_handler"
+ {
+ additional_dependency = <library>/boost/filesystem//boost_filesystem <library>/boost/system//boost_system <target-os>linux:<library>rt ;
+ }
+
+ if $(target_name) = "throwing_st"
+ {
+ additional_dependency = [ requires rtti ] ;
+ }
+
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>on $(LINKSHARED_BT) $(additional_dependency) : backtrace_$(p2[1]:B) ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>on $(LINKSHARED_AD2L) $(additional_dependency) : addr2line_$(p[1]:B) ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>on $(LINKSHARED_WIND) $(additional_dependency) : windbg_$(p[1]:B) ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>on $(LINKSHARED_WIND_CACHED) $(additional_dependency) : windbg_cached_$(p[1]:B) ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>on $(LINKSHARED_NOOP) $(additional_dependency) : noop_$(p[1]:B) ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>on $(LINKSHARED_BASIC) $(additional_dependency) : basic_$(p[1]:B) ] ;
+
+
+ ##### Tests with disabled debug symbols #####
+
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>off $(LINKSHARED_BT) $(additional_dependency) : backtrace_$(p[1]:B)_no_dbg ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>off $(LINKSHARED_AD2L) $(additional_dependency) : addr2line_$(p[1]:B)_no_dbg ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>off $(LINKSHARED_WIND) $(additional_dependency) : windbg_$(p[1]:B)_no_dbg ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>off $(LINKSHARED_WIND_CACHED) $(additional_dependency) : windbg_cached_$(p[1]:B)_no_dbg ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>off $(LINKSHARED_NOOP) $(additional_dependency) : noop_$(p[1]:B)_no_dbg ] ;
+ stacktrace_tests += [ run $(p) : : : <debug-symbols>off $(LINKSHARED_BASIC) $(additional_dependency) : basic_$(p[1]:B)_no_dbg ] ;
+
+}
+
+# Very long tests for detecting memory leaks and corruptions
+test-suite stacktrace_torture
+ :
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_BACKTRACE $(BT_DEPS) : torture_backtrace_ho ]
+ #[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_ADDR2LINE $(AD2L_DEPS) : torture_addr2line_ho ]
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on $(WIND_DEPS) : torture_windbg_ho ]
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_WINDBG_CACHED $(WICA_DEPS) : torture_windbg_cached_ho ]
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on $(FORCE_SYMBOL_EXPORT) $(BASIC_DEPS) : torture_basic_ho ]
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL $(BASIC_DEPS) : torture_basic_ho_empty ]
+
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_backtrace $(LINKSHARED_BT) : torture_backtrace_lib ]
+ #[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_addr2line $(LINKSHARED_AD2L) : torture_addr2line_lib ]
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_windbg $(LINKSHARED_WIND) : torture_windbg_lib ]
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_windbg_cached $(LINKSHARED_WIND_CACHED) : torture_windbg_cached_lib ]
+ [ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_basic $(LINKSHARED_BASIC) : torture_basic_lib ]
+ ;
+explicit stacktrace_torture ;
+
diff --git a/src/boost/libs/stacktrace/test/test.cpp b/src/boost/libs/stacktrace/test/test.cpp
new file mode 100644
index 000000000..66041e335
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/test.cpp
@@ -0,0 +1,282 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <boost/stacktrace/stacktrace_fwd.hpp>
+
+#include <boost/stacktrace.hpp>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+#include <cctype>
+
+#include <boost/core/lightweight_test.hpp>
+
+#include <boost/functional/hash.hpp>
+
+#include "test_impl.hpp"
+
+using boost::stacktrace::stacktrace;
+using boost::stacktrace::frame;
+
+
+#if (defined(BOOST_GCC) && defined(BOOST_WINDOWS) && !defined(BOOST_STACKTRACE_USE_BACKTRACE) && !defined(BOOST_STACKTRACE_USE_ADDR2LINE)) \
+ || defined(BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL)
+
+# define BOOST_STACKTRACE_TEST_SHOULD_OUTPUT_READABLE_NAMES 0
+#else
+# define BOOST_STACKTRACE_TEST_SHOULD_OUTPUT_READABLE_NAMES 1
+#endif
+
+void test_deeply_nested_namespaces() {
+ std::stringstream ss;
+ ss << return_from_nested_namespaces();
+ std::cout << ss.str() << '\n';
+#if BOOST_STACKTRACE_TEST_SHOULD_OUTPUT_READABLE_NAMES
+ BOOST_TEST(ss.str().find("main") != std::string::npos);
+
+ BOOST_TEST(ss.str().find("get_backtrace_from_nested_namespaces") != std::string::npos
+ || ss.str().find("1# return_from_nested_namespaces") != std::string::npos); // GCC with -O1 has strange inlining, so this line is true while the prev one is false.
+
+ BOOST_TEST(ss.str().find("return_from_nested_namespaces") != std::string::npos);
+#endif
+
+ stacktrace ns1 = return_from_nested_namespaces();
+ BOOST_TEST(ns1 != return_from_nested_namespaces()); // Different addresses in test_deeply_nested_namespaces() function
+}
+
+std::size_t count_unprintable_chars(const std::string& s) {
+ std::size_t result = 0;
+ for (std::size_t i = 0; i < s.size(); ++i) {
+ result += (std::isprint(s[i]) ? 0 : 1);
+ }
+
+ return result;
+}
+
+void test_frames_string_data_validity() {
+ stacktrace trace = return_from_nested_namespaces();
+ for (std::size_t i = 0; i < trace.size(); ++i) {
+ BOOST_TEST_EQ(count_unprintable_chars(trace[i].source_file()), 0);
+ BOOST_TEST_EQ(count_unprintable_chars(trace[i].name()), 0);
+ }
+
+ BOOST_TEST(to_string(trace).find('\0') == std::string::npos);
+}
+
+// Template parameter Depth is to produce different functions on each Depth. This simplifies debugging when one of the tests catches error
+template <std::size_t Depth>
+void test_nested(bool print = true) {
+ std::pair<stacktrace, stacktrace> res = function_from_library(Depth, function_from_main_translation_unit);
+
+ std::stringstream ss1, ss2;
+
+ ss1 << res.first;
+ ss2 << res.second;
+ if (print) {
+ std::cout << "'" << ss1.str() << "'\n\n" << ss2.str() << std::endl;
+ }
+ BOOST_TEST(!ss1.str().empty());
+ BOOST_TEST(!ss2.str().empty());
+
+ BOOST_TEST(ss1.str().find(" 0# ") != std::string::npos);
+ BOOST_TEST(ss2.str().find(" 0# ") != std::string::npos);
+
+ BOOST_TEST(ss1.str().find(" 1# ") != std::string::npos);
+ BOOST_TEST(ss2.str().find(" 1# ") != std::string::npos);
+
+ BOOST_TEST(ss1.str().find(" in ") != std::string::npos);
+ BOOST_TEST(ss2.str().find(" in ") != std::string::npos);
+
+#if BOOST_STACKTRACE_TEST_SHOULD_OUTPUT_READABLE_NAMES
+ BOOST_TEST(ss1.str().find("main") != std::string::npos);
+ BOOST_TEST(ss2.str().find("main") != std::string::npos);
+
+ BOOST_TEST(ss1.str().find("function_from_library") != std::string::npos);
+ BOOST_TEST(ss2.str().find("function_from_library") != std::string::npos);
+
+ BOOST_TEST(ss1.str().find("function_from_main_translation_unit") != std::string::npos);
+ BOOST_TEST(ss2.str().find("function_from_main_translation_unit") != std::string::npos);
+#endif
+}
+
+template <class Bt>
+void test_comparisons_base(Bt nst, Bt st) {
+ Bt cst(st);
+ st = st;
+ cst = cst;
+ BOOST_TEST(nst);
+ BOOST_TEST(st);
+#if !defined(BOOST_MSVC) && !defined(BOOST_STACKTRACE_USE_WINDBG)
+ // This is very dependent on compiler and link flags. No sane way to make it work, because
+ // BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
+ BOOST_TEST(nst[0] != st[0]);
+#endif
+
+ BOOST_TEST(nst != st);
+ BOOST_TEST(st != nst);
+ BOOST_TEST(st == st);
+ BOOST_TEST(nst == nst);
+
+ BOOST_TEST(nst != cst);
+ BOOST_TEST(cst != nst);
+ BOOST_TEST(cst == st);
+ BOOST_TEST(cst == cst);
+
+ BOOST_TEST(nst < st || nst > st);
+ BOOST_TEST(st < nst || nst < st);
+ BOOST_TEST(st <= st);
+ BOOST_TEST(nst <= nst);
+ BOOST_TEST(st >= st);
+ BOOST_TEST(nst >= nst);
+
+ BOOST_TEST(nst < cst || cst < nst);
+ BOOST_TEST(nst > cst || cst > nst);
+
+
+ BOOST_TEST(hash_value(nst) == hash_value(nst));
+ BOOST_TEST(hash_value(cst) == hash_value(st));
+
+ BOOST_TEST(hash_value(nst) != hash_value(cst));
+ BOOST_TEST(hash_value(st) != hash_value(nst));
+}
+
+void test_comparisons() {
+ stacktrace nst = return_from_nested_namespaces();
+ stacktrace st;
+ test_comparisons_base(nst, st);
+}
+
+void test_iterators() {
+ stacktrace st;
+
+ BOOST_TEST(st.begin() == st.begin());
+ BOOST_TEST(st.cbegin() == st.cbegin());
+ BOOST_TEST(st.crbegin() == st.crbegin());
+ BOOST_TEST(st.rbegin() == st.rbegin());
+
+ BOOST_TEST(st.begin() + 1 == st.begin() + 1);
+ BOOST_TEST(st.cbegin() + 1 == st.cbegin() + 1);
+ BOOST_TEST(st.crbegin() + 1 == st.crbegin() + 1);
+ BOOST_TEST(st.rbegin() + 1 == st.rbegin() + 1);
+
+ BOOST_TEST(st.end() == st.end());
+ BOOST_TEST(st.cend() == st.cend());
+ BOOST_TEST(st.crend() == st.crend());
+ BOOST_TEST(st.rend() == st.rend());
+
+ BOOST_TEST(st.end() > st.begin());
+ BOOST_TEST(st.end() > st.cbegin());
+ BOOST_TEST(st.cend() > st.cbegin());
+ BOOST_TEST(st.cend() > st.begin());
+
+ BOOST_TEST(st.size() == static_cast<std::size_t>(st.end() - st.begin()));
+ BOOST_TEST(st.size() == static_cast<std::size_t>(st.end() - st.cbegin()));
+ BOOST_TEST(st.size() == static_cast<std::size_t>(st.cend() - st.cbegin()));
+ BOOST_TEST(st.size() == static_cast<std::size_t>(st.cend() - st.begin()));
+
+ BOOST_TEST(st.size() == static_cast<std::size_t>(std::distance(st.rbegin(), st.rend())));
+ BOOST_TEST(st.size() == static_cast<std::size_t>(std::distance(st.crbegin(), st.rend())));
+ BOOST_TEST(st.size() == static_cast<std::size_t>(std::distance(st.crbegin(), st.crend())));
+ BOOST_TEST(st.size() == static_cast<std::size_t>(std::distance(st.rbegin(), st.crend())));
+
+
+ boost::stacktrace::stacktrace::iterator it = st.begin();
+ ++ it;
+ BOOST_TEST(it == st.begin() + 1);
+}
+
+void test_frame() {
+ stacktrace nst = return_from_nested_namespaces();
+ stacktrace st = make_some_stacktrace1();
+
+ const std::size_t min_size = (nst.size() < st.size() ? nst.size() : st.size());
+ BOOST_TEST(min_size > 2);
+
+ for (std::size_t i = 0; i < min_size; ++i) {
+ BOOST_TEST(st[i] == st[i]);
+ BOOST_TEST(st[i].source_file() == st[i].source_file());
+ BOOST_TEST(st[i].source_line() == st[i].source_line());
+ BOOST_TEST(st[i] <= st[i]);
+ BOOST_TEST(st[i] >= st[i]);
+
+ frame fv = nst[i];
+ BOOST_TEST(fv);
+ if (i > 1 && i < min_size - 3) { // Begin ...and end of the trace may match, skipping
+ BOOST_TEST(st[i] != fv);
+
+#if !(defined(BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL) && defined(BOOST_MSVC))
+ // MSVC can not get function name withhout debug symbols even if it is exported
+ BOOST_TEST(st[i].name() != fv.name());
+ BOOST_TEST(st[i] != fv);
+ BOOST_TEST(st[i] < fv || st[i] > fv);
+ BOOST_TEST(hash_value(st[i]) != hash_value(fv));
+#endif
+
+ if (st[i].source_line()) {
+ BOOST_TEST(st[i].source_file() != fv.source_file() || st[i].source_line() != fv.source_line());
+ }
+ BOOST_TEST(st[i]);
+ }
+
+ fv = st[i];
+ BOOST_TEST(hash_value(st[i]) == hash_value(fv));
+ }
+
+ boost::stacktrace::frame empty_frame;
+ BOOST_TEST(!empty_frame);
+ BOOST_TEST_EQ(empty_frame.source_file(), "");
+ BOOST_TEST_EQ(empty_frame.name(), "");
+ BOOST_TEST_EQ(empty_frame.source_line(), 0);
+}
+
+// Template parameter bool BySkip is to produce different functions on each BySkip. This simplifies debugging when one of the tests catches error
+template <bool BySkip>
+void test_empty_basic_stacktrace() {
+ typedef boost::stacktrace::stacktrace st_t;
+ st_t st = BySkip ? st_t(100500, 1024) : st_t(0, 0);
+
+ BOOST_TEST(!st);
+ BOOST_TEST(st.empty());
+ BOOST_TEST(st.size() == 0);
+ BOOST_TEST(st.begin() == st.end());
+ BOOST_TEST(st.cbegin() == st.end());
+ BOOST_TEST(st.cbegin() == st.cend());
+ BOOST_TEST(st.begin() == st.cend());
+
+ BOOST_TEST(st.rbegin() == st.rend());
+ BOOST_TEST(st.crbegin() == st.rend());
+ BOOST_TEST(st.crbegin() == st.crend());
+ BOOST_TEST(st.rbegin() == st.crend());
+
+ BOOST_TEST(hash_value(st) == hash_value(st_t(0, 0)));
+ BOOST_TEST(st == st_t(0, 0));
+ BOOST_TEST(!(st < st_t(0, 0)));
+ BOOST_TEST(!(st > st_t(0, 0)));
+}
+
+int main() {
+ test_deeply_nested_namespaces();
+ test_frames_string_data_validity();
+ test_nested<15>();
+ test_comparisons();
+ test_iterators();
+ test_frame();
+ test_empty_basic_stacktrace<true>();
+ test_empty_basic_stacktrace<false>();
+
+ BOOST_TEST(&make_some_stacktrace1 != &make_some_stacktrace2);
+ boost::stacktrace::stacktrace b1 = make_some_stacktrace1();
+ BOOST_TEST(b1.size() == 4);
+ boost::stacktrace::stacktrace b2 = make_some_stacktrace2();
+ BOOST_TEST(b2.size() == 4);
+ test_comparisons_base(make_some_stacktrace1(), make_some_stacktrace2());
+
+ test_nested<260>(false);
+ BOOST_TEST(boost::stacktrace::stacktrace(0, 1).size() == 1);
+ BOOST_TEST(boost::stacktrace::stacktrace(1, 1).size() == 1);
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/stacktrace/test/test_impl.cpp b/src/boost/libs/stacktrace/test/test_impl.cpp
new file mode 100644
index 000000000..06fd1d65d
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/test_impl.cpp
@@ -0,0 +1,72 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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)
+
+#define BOOST_STACKTRACE_TEST_IMPL_LIB 1
+#include "test_impl.hpp"
+
+using namespace boost::stacktrace;
+
+BOOST_ST_API BOOST_NOINLINE std::pair<stacktrace, stacktrace> function_from_library(int i, foo1_t foo1) {
+ if (i) {
+ return foo1(--i);
+ } else {
+ return foo1(i);
+ }
+}
+
+
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+namespace very_very_very_very_very_very_long_namespace {
+ BOOST_ST_API BOOST_NOINLINE stacktrace get_backtrace_from_nested_namespaces() {
+ return stacktrace();
+ }
+}}}}}}}}}}
+
+BOOST_ST_API BOOST_NOINLINE stacktrace return_from_nested_namespaces() {
+ using very_very_very_very_very_very_long_namespace::very_very_very_very_very_very_long_namespace::very_very_very_very_very_very_long_namespace
+ ::very_very_very_very_very_very_long_namespace::very_very_very_very_very_very_long_namespace::very_very_very_very_very_very_long_namespace
+ ::very_very_very_very_very_very_long_namespace::very_very_very_very_very_very_long_namespace::very_very_very_very_very_very_long_namespace
+ ::very_very_very_very_very_very_long_namespace::get_backtrace_from_nested_namespaces;
+
+ return get_backtrace_from_nested_namespaces();
+}
+
+BOOST_ST_API BOOST_NOINLINE boost::stacktrace::stacktrace make_some_stacktrace1_impl(int d = 0) {
+ boost::stacktrace::stacktrace result(0, 4);
+ if (result.size() < 4) {
+ if (d > 4) throw std::runtime_error("Stack is not growing in test OR stacktrace fails to work in `bar1` function.");
+ return make_some_stacktrace1_impl(d + 1);
+ }
+ return result;
+}
+
+BOOST_ST_API BOOST_NOINLINE boost::stacktrace::stacktrace make_some_stacktrace2_impl(int d = 0) {
+ boost::stacktrace::stacktrace result(0, 4);
+ if (result.size() < 4) {
+ if (d > 4) throw std::runtime_error("Stack is not growing in test OR stacktrace fails to work in `bar2` function.");
+ return make_some_stacktrace2_impl(d + 1);
+ }
+ return result;
+}
+
+BOOST_ST_API BOOST_NOINLINE boost::stacktrace::stacktrace make_some_stacktrace1() {
+ boost::stacktrace::stacktrace result = make_some_stacktrace1_impl();
+ return result;
+}
+
+BOOST_ST_API BOOST_NOINLINE boost::stacktrace::stacktrace make_some_stacktrace2() {
+ boost::stacktrace::stacktrace result = make_some_stacktrace2_impl();
+ return result;
+}
+
diff --git a/src/boost/libs/stacktrace/test/test_impl.hpp b/src/boost/libs/stacktrace/test/test_impl.hpp
new file mode 100644
index 000000000..3e6d1254c
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/test_impl.hpp
@@ -0,0 +1,58 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <boost/stacktrace/stacktrace.hpp>
+
+#if defined(BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP) || defined(BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP)
+#error "LexicalCast headers leaked into the boost/stacktrace/stacktrace.hpp"
+#endif
+
+#if !defined(BOOST_USE_WINDOWS_H) && defined(_WINDOWS_H)
+#error "windows.h header leaked into the boost/stacktrace/stacktrace.hpp"
+#endif
+
+#include <stdexcept>
+
+using namespace boost::stacktrace;
+
+#ifdef BOOST_STACKTRACE_DYN_LINK
+# ifdef BOOST_STACKTRACE_TEST_IMPL_LIB
+# define BOOST_ST_API BOOST_SYMBOL_EXPORT
+# else
+# define BOOST_ST_API BOOST_SYMBOL_IMPORT
+# endif
+#else
+# ifdef BOOST_STACKTRACE_TEST_EXPORTS_TABLE_USAGE
+# define BOOST_ST_API BOOST_SYMBOL_VISIBLE
+# else
+# define BOOST_ST_API
+# endif
+#endif
+
+typedef std::pair<boost::stacktrace::stacktrace, boost::stacktrace::stacktrace> st_pair;
+typedef st_pair (*foo1_t)(int i);
+BOOST_ST_API st_pair function_from_library(int i, foo1_t foo1);
+BOOST_ST_API boost::stacktrace::stacktrace return_from_nested_namespaces();
+BOOST_ST_API boost::stacktrace::stacktrace make_some_stacktrace1();
+BOOST_ST_API boost::stacktrace::stacktrace make_some_stacktrace2();
+
+#ifdef BOOST_STACKTRACE_TEST_EXPORTS_TABLE_USAGE
+ BOOST_SYMBOL_VISIBLE
+#endif
+inline st_pair function_from_main_translation_unit(int i) {
+ if (i) {
+ return function_from_library(i - 1, function_from_main_translation_unit);
+ }
+
+ std::pair<stacktrace, stacktrace> ret;
+ try {
+ throw std::logic_error("test");
+ } catch (const std::logic_error& /*e*/) {
+ ret.second = stacktrace();
+ return ret;
+ }
+}
diff --git a/src/boost/libs/stacktrace/test/test_noop.cpp b/src/boost/libs/stacktrace/test/test_noop.cpp
new file mode 100644
index 000000000..997dcfe0c
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/test_noop.cpp
@@ -0,0 +1,58 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 "test_impl.hpp"
+
+#include <boost/stacktrace.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <stdexcept>
+
+
+#include <boost/functional/hash.hpp>
+
+using boost::stacktrace::stacktrace;
+using boost::stacktrace::frame;
+
+void test_deeply_nested_namespaces() {
+ BOOST_TEST(return_from_nested_namespaces().size() == 0);
+ BOOST_TEST(return_from_nested_namespaces().empty());
+ BOOST_TEST(!return_from_nested_namespaces());
+}
+
+void test_nested() {
+ std::pair<stacktrace, stacktrace> res = function_from_library(15, function_from_main_translation_unit);
+
+ BOOST_TEST(!res.first);
+ BOOST_TEST(res.first.empty());
+ BOOST_TEST(res.first.size() == 0);
+
+ BOOST_TEST(res.second <= res.first);
+ BOOST_TEST(res.second >= res.first);
+ BOOST_TEST(res.second == res.first);
+ BOOST_TEST(res.second == res.first);
+ BOOST_TEST(!(res.second > res.first));
+}
+
+void test_empty_frame() {
+ boost::stacktrace::frame empty_frame;
+ BOOST_TEST(!empty_frame);
+ BOOST_TEST(empty_frame.source_file() == "");
+ BOOST_TEST(empty_frame.name() == "");
+ BOOST_TEST(empty_frame.source_line() == 0);
+
+ boost::stacktrace::frame f(0);
+ BOOST_TEST(f.name() == "");
+ BOOST_TEST(f.source_file() == "");
+ BOOST_TEST(f.source_line() == 0);
+}
+
+int main() {
+ test_deeply_nested_namespaces();
+ test_nested();
+ test_empty_frame();
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/stacktrace/test/test_num_conv.cpp b/src/boost/libs/stacktrace/test/test_num_conv.cpp
new file mode 100644
index 000000000..dbe0b23cb
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/test_num_conv.cpp
@@ -0,0 +1,71 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 <boost/stacktrace/detail/to_dec_array.hpp>
+#include <boost/stacktrace/detail/to_hex_array.hpp>
+#include <boost/stacktrace/detail/try_dec_convert.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+#include <string>
+#include <iostream>
+
+
+void test_to_hex_array() {
+ const void* ptr = 0;
+ BOOST_TEST(std::string(boost::stacktrace::detail::to_hex_array(ptr).data()).find("0x0") != std::string::npos);
+
+ ptr = reinterpret_cast<const void*>(0x10);
+ BOOST_TEST(std::string(boost::stacktrace::detail::to_hex_array(ptr).data()).find("10") != std::string::npos);
+
+ ptr = reinterpret_cast<void*>(0x19);
+ BOOST_TEST(std::string(boost::stacktrace::detail::to_hex_array(ptr).data()).find("19") != std::string::npos);
+
+ ptr = reinterpret_cast<void*>(0x999999);
+ BOOST_TEST(std::string(boost::stacktrace::detail::to_hex_array(ptr).data()).find("999999") != std::string::npos);
+}
+
+void test_to_dec_array() {
+ BOOST_TEST_EQ(std::string(boost::stacktrace::detail::to_dec_array(0).data()), std::string("0"));
+ BOOST_TEST_EQ(std::string(boost::stacktrace::detail::to_dec_array(10).data()), std::string("10"));
+ BOOST_TEST_EQ(std::string(boost::stacktrace::detail::to_dec_array(19).data()), std::string("19"));
+ BOOST_TEST_EQ(std::string(boost::stacktrace::detail::to_dec_array(999999).data()), std::string("999999"));
+}
+
+void test_try_dec_convert() {
+ std::size_t res = 0;
+
+ BOOST_TEST(boost::stacktrace::detail::try_dec_convert("0", res));
+ BOOST_TEST(res == 0);
+
+ BOOST_TEST(boost::stacktrace::detail::try_dec_convert("+0", res));
+ BOOST_TEST(res == 0);
+
+ BOOST_TEST(boost::stacktrace::detail::try_dec_convert("10", res));
+ BOOST_TEST(res == 10);
+
+ BOOST_TEST(boost::stacktrace::detail::try_dec_convert("19", res));
+ BOOST_TEST(res == 19);
+
+ BOOST_TEST(boost::stacktrace::detail::try_dec_convert("+19", res));
+ BOOST_TEST(res == 19);
+
+ BOOST_TEST(boost::stacktrace::detail::try_dec_convert("9999", res));
+ BOOST_TEST(res == 9999);
+
+ BOOST_TEST(!boost::stacktrace::detail::try_dec_convert("q", res));
+ BOOST_TEST(!boost::stacktrace::detail::try_dec_convert("0z", res));
+ BOOST_TEST(!boost::stacktrace::detail::try_dec_convert("0u", res));
+ BOOST_TEST(!boost::stacktrace::detail::try_dec_convert("+0u", res));
+}
+
+
+int main() {
+ test_to_hex_array();
+ test_to_dec_array();
+ test_try_dec_convert();
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/stacktrace/test/test_void_ptr_cast.cpp b/src/boost/libs/stacktrace/test/test_void_ptr_cast.cpp
new file mode 100644
index 000000000..5e569649a
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/test_void_ptr_cast.cpp
@@ -0,0 +1,79 @@
+// Copyright 2017 Antony Polukhin.
+//
+// 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 <boost/stacktrace/detail/void_ptr_cast.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+int foo1_func(int) { return 0; }
+void foo2_func(int, int, ...) {}
+
+struct test_struct {
+ int foo1_memb(int) const { return 0; }
+ void foo2_memb(int, int, ...) {}
+};
+
+template <class F1, class F2>
+void test(F1 foo1, F2 foo2) {
+ using boost::stacktrace::detail::void_ptr_cast;
+
+ typedef void(*void_f_ptr)();
+
+ // Function/variable to void(*)()
+ void_f_ptr fp1 = void_ptr_cast<void_f_ptr>(foo1);
+ void_f_ptr fp2 = void_ptr_cast<void_f_ptr>(foo2);
+ BOOST_TEST(fp1);
+ BOOST_TEST(fp2);
+ BOOST_TEST(fp1 != fp2);
+
+ // Function/variable to void*
+ void* vp1 = void_ptr_cast<void*>(foo1);
+ void* vp2 = void_ptr_cast<void*>(foo2);
+ BOOST_TEST(vp1);
+ BOOST_TEST(vp2);
+ BOOST_TEST(vp1 != vp2);
+
+ // void* to void(*)()
+ void_f_ptr fp1_2 = void_ptr_cast<void_f_ptr>(vp1);
+ void_f_ptr fp2_2 = void_ptr_cast<void_f_ptr>(vp2);
+ BOOST_TEST(fp1_2);
+ BOOST_TEST(fp2_2);
+ BOOST_TEST(fp1_2 != fp2_2);
+ BOOST_TEST(fp1 == fp1_2);
+ BOOST_TEST(fp2 == fp2_2);
+
+ // void(*)() to void*
+ BOOST_TEST(void_ptr_cast<void*>(fp1) == vp1);
+ BOOST_TEST(void_ptr_cast<void*>(fp2) == vp2);
+
+ // void(*)() to function/variable
+ BOOST_TEST(void_ptr_cast<F1>(fp1) == foo1);
+ BOOST_TEST(void_ptr_cast<F2>(fp2) == foo2);
+
+ // void* to function/variable
+ BOOST_TEST(void_ptr_cast<F1>(vp1) == foo1);
+ BOOST_TEST(void_ptr_cast<F2>(vp2) == foo2);
+}
+
+int main() {
+ // Testing for functions
+ test(foo1_func, foo2_func);
+
+ typedef void(func_t)();
+ test(
+ boost::stacktrace::detail::void_ptr_cast<func_t* const>(foo1_func),
+ boost::stacktrace::detail::void_ptr_cast<func_t* const>(foo2_func)
+ );
+
+ // Testing for variables (just in case...)
+ int i = 0;
+ double j= 1;
+ test(&i, &j);
+
+
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/stacktrace/test/thread_safety_checking.cpp b/src/boost/libs/stacktrace/test/thread_safety_checking.cpp
new file mode 100644
index 000000000..ce43a06dc
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/thread_safety_checking.cpp
@@ -0,0 +1,72 @@
+// Copyright Antony Polukhin, 2016-2020.
+//
+// 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 "test_impl.hpp"
+#include <boost/stacktrace/stacktrace_fwd.hpp>
+
+#include <sstream>
+
+#include <boost/stacktrace.hpp>
+#include <boost/thread.hpp>
+#include <boost/optional.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include <boost/timer/timer.hpp>
+
+using boost::stacktrace::stacktrace;
+
+
+void main_test_loop() {
+ std::size_t loops = 100;
+ int Depth = 25;
+
+ boost::optional<std::pair<stacktrace, stacktrace> > ethalon;
+ std::stringstream ss_ethalon;
+
+ while (--loops) {
+ std::pair<stacktrace, stacktrace> res = function_from_library(Depth, function_from_main_translation_unit);
+ if (ethalon) {
+ BOOST_TEST(res == *ethalon);
+
+ std::stringstream ss;
+ ss << res.first;
+ BOOST_TEST(ss.str() == ss_ethalon.str());
+ } else {
+ ethalon = res;
+ ss_ethalon << ethalon->first;
+ }
+ }
+}
+
+#if defined(BOOST_STACKTRACE_TEST_COM_PREINIT_MT) || defined(BOOST_STACKTRACE_TEST_COM_PREINIT_ST)
+# include <windows.h>
+# include "dbgeng.h"
+#endif
+
+int main() {
+#if defined(BOOST_STACKTRACE_TEST_COM_PREINIT_MT)
+ ::CoInitializeEx(0, COINIT_MULTITHREADED);
+#elif defined(BOOST_STACKTRACE_TEST_COM_PREINIT_ST)
+ ::CoInitializeEx(0, COINIT_APARTMENTTHREADED);
+#endif
+
+ boost::timer::auto_cpu_timer t;
+
+ boost::thread t1(main_test_loop);
+ boost::thread t2(main_test_loop);
+ boost::thread t3(main_test_loop);
+ main_test_loop();
+
+ t1.join();
+ t2.join();
+ t3.join();
+
+#if defined(BOOST_STACKTRACE_TEST_COM_PREINIT_MT) || defined(BOOST_STACKTRACE_TEST_COM_PREINIT_ST)
+ ::CoUninitialize();
+#endif
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/stacktrace/test/torture.cpp b/src/boost/libs/stacktrace/test/torture.cpp
new file mode 100644
index 000000000..2df475deb
--- /dev/null
+++ b/src/boost/libs/stacktrace/test/torture.cpp
@@ -0,0 +1,26 @@
+// Copyright Antony Polukhin, 2018.
+//
+// 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)
+
+
+// This file tests for memory leaks. Some of the backtrace implementations
+// consume memory for internal needs and incorrect usage of those implementations
+// could lead to segfaults. Sanitizers do not detect such misuse, but this
+// test and `top` does.
+
+
+#include <boost/stacktrace.hpp>
+#include <iostream>
+
+#include "test_impl.hpp"
+
+int main() {
+ int result = 0;
+ for (unsigned i = 0; i < 10000000; ++i) {
+ result += make_some_stacktrace1()[0].source_line();
+ }
+
+ std::cerr << "OK\nLines count " << result;
+}