diff --git a/include/boost/stacktrace/detail/backend.hpp b/include/boost/stacktrace/detail/backend.hpp
index 1f376b1..ab57d1b 100644
--- a/include/boost/stacktrace/detail/backend.hpp
+++ b/include/boost/stacktrace/detail/backend.hpp
@@ -63,7 +63,7 @@ namespace boost { namespace stacktrace { namespace detail {
// Class that implements the actual backtracing
class backend {
public:
- BOOST_STACKTRACE_FUNCTION static std::size_t collect(void** memory, std::size_t size) BOOST_NOEXCEPT;
+ BOOST_NOINLINE BOOST_STACKTRACE_FUNCTION static std::size_t collect(void** memory, std::size_t size) BOOST_NOEXCEPT;
BOOST_STACKTRACE_FUNCTION static std::string get_name(const void* addr);
BOOST_STACKTRACE_FUNCTION static std::string get_source_file(const void* addr);
BOOST_STACKTRACE_FUNCTION static std::size_t get_source_line(const void* addr);
diff --git a/include/boost/stacktrace/stacktrace.hpp b/include/boost/stacktrace/stacktrace.hpp
index 3f1c2a0..23d70ff 100644
--- a/include/boost/stacktrace/stacktrace.hpp
+++ b/include/boost/stacktrace/stacktrace.hpp
@@ -36,7 +36,7 @@ class basic_stacktrace {
boost::container::vector impl_;
/// @cond
- static const std::size_t frames_to_skip = 0;
+ static const std::size_t frames_to_skip = 2;
void fill(void** begin, std::size_t size) {
if (size < frames_to_skip) {
@@ -50,14 +50,43 @@ class basic_stacktrace {
);
}
}
+ /// @endcond
- BOOST_NOINLINE void init(std::size_t max_depth) BOOST_NOEXCEPT {
+public:
+ typedef typename boost::container::vector::value_type value_type;
+ typedef typename boost::container::vector::allocator_type allocator_type;
+ typedef typename boost::container::vector::const_pointer pointer;
+ typedef typename boost::container::vector::const_pointer const_pointer;
+ typedef typename boost::container::vector::const_reference reference;
+ typedef typename boost::container::vector::const_reference const_reference;
+ typedef typename boost::container::vector::size_type size_type;
+ typedef typename boost::container::vector::difference_type difference_type;
+ typedef typename boost::container::vector::const_iterator iterator;
+ typedef typename boost::container::vector::const_iterator const_iterator;
+ typedef typename boost::container::vector::const_reverse_iterator reverse_iterator;
+ typedef typename boost::container::vector::const_reverse_iterator const_reverse_iterator;
+
+ /// @brief Stores the current function call sequence inside the class.
+ ///
+ /// @b Complexity: O(N) where N is call sequence length, O(1) for noop backend.
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
+ ///
+ /// @param max_depth max stack depth
+ ///
+ /// @throws Nothing. Note that default construction of allocator may throw, hovewer it is
+ /// performed outside the constructor and exception in `allocator_type()` would not result in calling `std::terminate`.
+ BOOST_NOINLINE explicit basic_stacktrace(std::size_t max_depth = static_cast(-1), const allocator_type& a = allocator_type()) BOOST_NOEXCEPT
+ : impl_(a)
+ {
const size_t buffer_size = 128;
if (!max_depth) {
return;
}
- max_depth += frames_to_skip;
+ if (static_cast(-1) - frames_to_skip >= max_depth) {
+ max_depth += frames_to_skip;
+ }
try {
{ // Fast path without additional allocations
@@ -83,47 +112,10 @@ class basic_stacktrace {
buf.resize(buf.size() * 2);
} while (1);
-
-
} catch (...) {
// ignore exception
}
}
- /// @endcond
-
-public:
- typedef typename boost::container::vector::value_type value_type;
- typedef typename boost::container::vector::allocator_type allocator_type;
- typedef typename boost::container::vector::const_pointer pointer;
- typedef typename boost::container::vector::const_pointer const_pointer;
- typedef typename boost::container::vector::const_reference reference;
- typedef typename boost::container::vector::const_reference const_reference;
- typedef typename boost::container::vector::size_type size_type;
- typedef typename boost::container::vector::difference_type difference_type;
- typedef typename boost::container::vector::const_iterator iterator;
- typedef typename boost::container::vector::const_iterator const_iterator;
- typedef typename boost::container::vector::const_reverse_iterator reverse_iterator;
- typedef typename boost::container::vector::const_reverse_iterator const_reverse_iterator;
-
- /// @brief Stores the current function call sequence inside the class.
- ///
- /// @b Complexity: O(N) where N is call sequence length, O(1) for noop backend.
- ///
- /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
- ///
- /// @throws Nothing. Note that default construction of allocator may throw, hovewer it is
- /// performed outside the constructor and exception in `allocator_type()` would not result in calling `std::terminate`.
- BOOST_FORCEINLINE explicit basic_stacktrace(const allocator_type& a = allocator_type()) BOOST_NOEXCEPT
- : impl_(a)
- {
- init(static_cast(-1));
- }
-
- BOOST_FORCEINLINE explicit basic_stacktrace(std::size_t max_depth, const allocator_type& a = allocator_type()) BOOST_NOEXCEPT
- : impl_(a)
- {
- init(max_depth);
- }
#ifdef BOOST_STACKTRACE_DOXYGEN_INVOKED
/// @b Complexity: O(st.size())
@@ -136,22 +128,26 @@ public:
/// @b Async-Handler-Safety: Safe if Allocator construction and copying are async signal safe.
basic_stacktrace(basic_stacktrace&& st) = default;
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator::deallocate is async signal safe.
+ ~basic_stacktrace() BOOST_NOEXCEPT = default;
+#endif
+
/// @b Complexity: O(st.size())
///
/// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
- basic_stacktrace& operator=(const basic_stacktrace& st) = default;
+ basic_stacktrace& operator=(const basic_stacktrace& st) {
+ impl_ = st.impl_;
+ return *this;
+ }
+/* TODO:
/// @b Complexity: O(st.size())
///
/// @b Async-Handler-Safety: Safe if Allocator construction and copying are async signal safe.
basic_stacktrace& operator=(basic_stacktrace&& st) = default;
-
- /// @b Complexity: O(1)
- ///
- /// @b Async-Handler-Safety: Safe if Allocator::deallocate are async signal safe..
- ~basic_stacktrace() BOOST_NOEXCEPT = default;
-#endif
-
+*/
/// @returns Number of function names stored inside the class.
///
/// @b Complexity: O(1)
diff --git a/test/test.cpp b/test/test.cpp
index 5416683..a34106c 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -36,10 +36,8 @@ void test_deeply_nested_namespaces() {
std::cout << ss.str() << '\n';
BOOST_TEST(ss.str().find("main") != std::string::npos);
-#if defined(BOOST_STACKTRACE_DYN_LINK)
- BOOST_TEST(ss.str().find("get_backtrace_from_nested_namespaces") != std::string::npos
- || ss.str().find("return_from_nested_namespaces") != std::string::npos);
-#endif
+ BOOST_TEST(ss.str().find("get_backtrace_from_nested_namespaces") != std::string::npos);
+ BOOST_TEST(ss.str().find("return_from_nested_namespaces") != std::string::npos);
stacktrace ns1 = return_from_nested_namespaces();
BOOST_TEST(ns1 != return_from_nested_namespaces()); // Different addresses in test_deeply_nested_namespaces() function
@@ -193,9 +191,9 @@ void test_frame() {
BOOST_TEST(st[i] <= st[i]);
BOOST_TEST(st[i] >= st[i]);
- frame fv = nst[2];
+ frame fv = nst[0];
BOOST_TEST(fv);
- if (i >= 2 && i < min_size - 3) { // Begin and end of the trace may match, skipping them
+ if (i < min_size - 3) { // End of the trace may match, skipping
BOOST_TEST(st[i] != fv);
BOOST_TEST(st[i].name() != fv.name());
BOOST_TEST(st[i] != fv);
@@ -215,7 +213,7 @@ void test_frame() {
BOOST_TEST(empty_frame.name() == "");
BOOST_TEST(empty_frame.source_line() == 0);
}
-/*
+
void test_empty_basic_stacktrace() {
typedef boost::stacktrace::stacktrace st_t;
st_t st(0);
@@ -233,11 +231,11 @@ void test_empty_basic_stacktrace() {
BOOST_TEST(st.crbegin() == st.crend());
BOOST_TEST(st.rbegin() == st.crend());
- BOOST_TEST(hash_value(st) == hash_value(st_t()));
- BOOST_TEST(st == st_t());
- BOOST_TEST(!(st < st_t()));
- BOOST_TEST(!(st > st_t()));
-}*/
+ BOOST_TEST(hash_value(st) == hash_value(st_t(0)));
+ BOOST_TEST(st == st_t(0));
+ BOOST_TEST(!(st < st_t(0)));
+ BOOST_TEST(!(st > st_t(0)));
+}
int main() {
test_deeply_nested_namespaces();
@@ -245,7 +243,7 @@ int main() {
test_comparisons();
test_iterators();
test_frame();
- //test_empty_basic_stacktrace();
+ test_empty_basic_stacktrace();
BOOST_TEST(&bar1 != &bar2);
boost::stacktrace::stacktrace b1 = bar1();