C++23stlexpert
std::stacktrace, std::stacktrace_entry, std::basic_stacktrace (C++23 Addition)
C++23 · Completing Modern · Compiler flag: -std=c++23
Explanation
Capture and manipulate stack traces for debugging.
Real-World Scenario
Log stack traces on errors in a server application.
Quick Snippet
snippet.cpp
#include <stacktrace> auto trace = std::stacktrace::current();Full Example
stacktrace.cpp
// CodeNebula - C++23 Example: std::stacktrace
// Compile: g++ -std=c++23 -Wall -Wextra -lstdc++_libbacktrace -o example stacktrace.cpp
// Note: Requires GCC 12+ / Clang 19+ / MSVC 19.34+
// GCC needs -lstdc++_libbacktrace; MSVC links automatically.
// Compile with -g for meaningful function names and line numbers.
// std::stacktrace captures the current call stack at runtime.
// Useful for debugging, error reporting, and logging.
#include <iostream>
#include <stacktrace>
#include <string>
void print_trace(const std::string& label) {
std::cout << "--- " << label << " ---" << std::endl;
auto trace = std::stacktrace::current();
std::cout << "Stack depth: " << trace.size() << " frames" << std::endl;
for (std::size_t i = 0; i < trace.size() && i < 5; ++i) {
const auto& entry = trace[i];
std::cout << " [" << i << "] ";
if (!entry.description().empty())
std::cout << entry.description();
else
std::cout << "(no description)";
std::cout << std::endl;
// source_file and source_line may be empty without debug info
if (!entry.source_file().empty()) {
std::cout << " at " << entry.source_file()
<< ":" << entry.source_line() << std::endl;
}
}
std::cout << std::endl;
}
void function_c() {
print_trace("Inside function_c");
}
void function_b() {
function_c();
}
void function_a() {
function_b();
}
// Capture stacktrace in an exception-like error report
struct ErrorReport {
std::string message;
std::stacktrace trace;
ErrorReport(const std::string& msg)
: message(msg), trace(std::stacktrace::current()) {}
void print() const {
std::cout << "ERROR: " << message << std::endl;
std::cout << "Captured " << trace.size() << " frames" << std::endl;
// Print top 3 frames
for (std::size_t i = 0; i < trace.size() && i < 3; ++i) {
std::cout << " [" << i << "] " << trace[i].description() << std::endl;
}
}
};
void risky_operation() {
ErrorReport err("something went wrong in risky_operation");
err.print();
}
int main() {
std::cout << "=== std::stacktrace ===" << std::endl;
// Capture current stacktrace
auto here = std::stacktrace::current();
std::cout << "Current stack has " << here.size() << " frame(s)" << std::endl;
// Nested call to show stack depth
std::cout << "\n=== Nested calls ===" << std::endl;
function_a();
// Stacktrace in error reporting
std::cout << "=== Error reporting with stacktrace ===" << std::endl;
risky_operation();
// Convert to string
std::cout << "\n=== to_string ===" << std::endl;
auto trace = std::stacktrace::current();
std::string trace_str = std::to_string(trace);
std::cout << "Trace as string (first 120 chars):" << std::endl;
std::cout << trace_str.substr(0, 120) << "..." << std::endl;
return 0;
}
/*
Expected output (exact frames vary by platform and compiler):
=== std::stacktrace ===
Current stack has N frame(s)
=== Nested calls ===
--- Inside function_c ---
Stack depth: N frames
[0] print_trace(...)
[1] function_c()
[2] function_b()
[3] function_a()
[4] main
=== Error reporting with stacktrace ===
ERROR: something went wrong in risky_operation
Captured N frames
[0] risky_operation()
[1] main
...
=== to_string ===
Trace as string (first 120 chars):
(platform-dependent stack trace text)...
*/
Run command
g++ -std=c++23 -Wall -Wextra -lstdc++_libbacktrace -o example stacktrace.cpp