Skip to content

std::stacktrace (C++23) ​

One-Liner ​

Capture the current call stack anywhere in your code and get each frame's function name, source file, and line number — the standard tool for program introspection and crash diagnostics, replacing clumsy approaches like the backtrace() family.

#include <stacktrace>

GCC linking pitfall (tested)

GCC's <stacktrace> symbols are not in the main library; you must link the experimental library separately: GCC 16+ uses -lstdc++exp (note: no underscore), GCC 12–15 uses -lstdc++_exp (with underscore). In CMake, write target_link_libraries(target PRIVATE stdc++exp). Miss the link and you get undefined reference to std::__stacktrace_impl::_S_current.

Core API Cheat Sheet ​

OperationSignatureDescription
Capture current stackstd::stacktrace::current()Returns a snapshot of the current call stack
With skipped framesstacktrace::current(skip, max_depth)Skips the first skip frames, takes at most max_depth
Stack depthst.size()Number of frames
Get one framest[i]Yields a stacktrace_entry
Frame descriptionentry.description()Human-readable string with the function name, address, and more
Frame source locationentry.source_file() / source_line()Source file name and line number (requires debug symbols)
Stream outputstd::cout << stPrints the whole stack directly

Minimal Example ​

C++
// Standard: C++23
// Build: g++ -std=c++23 demo.cpp -lstdc++exp     (GCC 16+)
#include <stacktrace>
#include <iostream>

void inner() {
    auto st = std::stacktrace::current();
    std::cout << "depth=" << st.size() << "\n";
    for (std::size_t i = 0; i < st.size(); ++i)
        std::cout << "  #" << i << " " << st[i] << "\n";
}
void outer() { inner(); }
int main() { outer(); }

Actual output (GCC 16.1.1, -std=c++23 -lstdc++exp):

text
depth=6
  #0  inner() [0x5ca9fa0aa28d]
  #1  outer() [0x5ca9fa0aa3d4]
  #2  main [0x5ca9fa0aa3e0]
  #3  <unknown> [0x7f1709227740]
  #4  __libc_start_main [0x7f1709227878]
  #5  _start [0x5ca9fa0aa184]

Function names for our own code (inner/outer/main) resolved fine; the dynamic-library frames showing <unknown> is normal — those addresses were never symbolized.

Embedded Applicability: Low ​

  • Depends on the symbol table and runtime stack unwinding — usually unavailable on bare metal and RTOS, or requires a dedicated port
  • Symbol information bloats the image; after strip (-s) only addresses remain
  • Embedded work more commonly relies on hardware breakpoints, ITM, SEGGER RTT, or custom crashdump backtraces
  • It does come in handy on the host side: tooling, test stubs, and CI failure diagnostics

Compiler Support ​

GCCClangMSVC
121619.34

See Also ​


Part of the content referenced from cppreference.com, licensed under CC-BY-SA 4.0

pdf-latest-4-g85128cc · 85128cc · 2026-10-05