1 year ago

#339190

test-img

Steve Lorimer

Is it possible to generate a stacktrace with valid frame symbols / function names?

I am trying to generate a stacktrace at the point in which an exception is thrown.

To do so, I have a custom exception class which stores the current stacktrace as a member, allowing me to log it when the exception is caught.

class generic_error : public std::runtime_error
{
public:
  generic_error(const char* err)
    : std::runtime_error{err}
    , stacktrace_{utl::stacktrace()}
  {}

  const std::string& stacktrace() const
  {
    return stacktrace_;
  }
private:
  std::string stacktrace_;
};

I am using backtrace and backtrace_symbols together with abi::__cxa_demangle, but am getting many stack frames without an address from which I can obtain a function name etc.

I have also tried to use boost::stacktrace in case it was a mistake in my implentation, but to no evail.

In both cases I get a stacktrace with many empty frames (eg: frame 3-12 and 14-17 below)

 0# utl:stacktrace[abi:cxx11]() in ./test_app
 1# app::generic_error::generic_error(char const*) in ./test_app
 2# app::exception_factory::create(const char*) in ./test_app
 3# 0x00000000027329FA in ./test_app
 4# 0x0000000002732B06 in ./test_app
 5# 0x0000000002747FC7 in ./test_app
 6# 0x000000000273FEAE in ./test_app
 7# 0x0000000002732CF3 in ./test_app
 8# 0x0000000002732D3E in ./test_app
 9# 0x0000000002732D7B in ./test_app
10# 0x000000000272BEF5 in ./test_app
11# 0x0000000002732DA5 in ./test_app
12# 0x0000000002732DCD in ./test_app
13# stdext::inplace_function<void (std::ostream&), 4608ul, 16ul>::operator()(std::ostream&) const in ./test_app
14# 0x000000000275F523 in ./test_app
15# 0x0000000002759927 in ./test_app
16# 0x0000000002755BDE in ./test_app
17# 0x0000000002759AE5 in ./test_app
18# boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) in ./test_app
19# boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) in ./test_app
20# boost::asio::detail::scheduler::run(boost::system::error_code&) in ./test_app
21# boost::asio::io_context::run() in ./test_app
  • I am building in debug mode (-g)

  • I have no optimistaion flag (-On) present

  • I also have -ggdb3 flag set.

  • I have -rdynamic linker flag set

  • I am linking -ldl

  • I have ensured that I do not have -fvisibility=hidden etc in my compiler flags.

  • I have -fno-omit-frame-pointer set

Questions:

Given I have debug symbols present in my binary, why does my stacktrace not work?

I am 99% confident I have had success with my approach before, so I'm thinking this must be due to the visibility changes in gcc?

I see there is a std::stracktrace utility being added in C++23, and the notes make reference to boost::stacktrace::basic_stacktrace, which suggest boost::stracktrace is a reference implementation... however, given boost::stracktrace is not working for me, what would std::stacktrace do differently to make it work?

Were I to load my app in gdb for example, gdb would have access to the full stack, so presumably it must be possible to obtain the full call stack? Is there an alternative method of obtaining stacktrace symbols?

c++

gcc

stack-trace

0 Answers

Your Answer

Accepted video resources