TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #1153 2.48K
​​Stacktrace
#опытным

Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да, по сообщению об ошибке и типу исключения обычно можно отследить нужное место в программе. Но как исполнение дошло до этой точки? А это ведь самое важное - понимание, при каком сценарии наступила исключительная ситуация.

Когда мы дебажим программу, мы видим, что привело к точке останова. В любом дебаггере есть команда аля backtrace, которая выводит визуализированный стек вызовов. Например так:

(gdb) bt
#0 0x0000555555556a2a in apply_discount (order_id=1001, total=250.5) at discount.c:45
#1 0x0000555555556b10 in calculate_final_price (order=0x7fffffffde40) at order_engine.c:89
#2 0x0000555555556c45 in process_payment (order=0x7fffffffde40, method=0x555555758020 "credit") at payment.c:120
#3 0x0000555555556d8a in handle_order_request (request=0x7fffffffdf00) at api_handler.c:56
#4 0x0000555555556e20 in main () at server.c:32


В данном случае мы видим, что ошибка произошла в функции apply_discount, которую вызвал калькулятор цены при обработке запроса платежа. То есть в данном случае мы видим четкий сценарий возникновения ошибки

И вот было бы круто видеть такую картину каждый раз, когда в catch залетает исключение. Да и в принципе в любой ситуации, когда нам интересна информация из трейса.

С++23 предоставил нам возможность конструировать кастомные исключения с описанием стека вызова внутри. Делается это через класс std::stacktrace. Работает он очень просто:

#include <iostream>
#include <stacktrace>

std::stacktrace bar() {
auto trace = std::stacktrace::current();
return trace;
}

std::stacktrace foo() {
return bar();
}

int main() {
auto trace = foo();
std::cout << trace << '\n';
}


С помощью статического метода std::stacktrace::current() можно получить стек вызовов в моменте использования метода. Для типа std::stacktrace даже перегружен оператор вывода в поток, поэтому вы спокойно можете вывести сырой трейс на консоль. Вывод может быть примерно таким:

0#  bar() at /app/example.cpp:5 [0x4033ee]
1# foo() at /app/example.cpp:10 [0x40340d]
2# main at /app/example.cpp:14 [0x403428]
3# <unknown> [0x74eed1a2a1c9]
4# libc_start_main [0x74eed1a2a28a]
5# start [0x403304]


Вот примерчик, чтобы поиграться.

Теперь легко сделать свое исключение со стектрейсом и прочими прелестями.

class TracedException : public std::exception {
std::string message;
std::stacktrace trace;
mutable std::string full_what; // cached formatted output

public:
explicit TracedException(std::string msg)
: message_(std::move(msg))
// Capture the stack RIGHT when the exception is created
// skip = 1 means skip this constructor from the trace
, trace_(std::stacktrace::current(/skip=/1))
{}

const std::stacktrace& trace() const noexcept {
return trace_;
}

const char* what() const noexcept override {
if (full_what_.empty()) {
full_what_ = message_ + "\n\n--- Stack Trace ---\n"
+ std::to_string(trace_);
}
return full_what_.c_str();
}
};


Трейс захватываем в конструкторе, собственно ровно в том месте, откуда и летит исключение. И скипаем один фрейм сверху, чтобы не учитывать конструктор, с помощью параметра метода std::stacktrace::current. В целом, использование очень похоже на std::source_location.

Know your origin. Stay cool.

#cpp23
  • ❤ 12
  • 👍 6
  • 🔥 5
  • 😁 2
More from @grokaemcpp
  1. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  2. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  3. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  4. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  5. Sep 25, 2026​​std::spanstream #опытным Радостная весть для всех, кто пользуется iostreams! В C++23 доб…
  6. Sep 23, 2026​​Identity объекта #опытным На пространстве интернетов мне попался шортс, где довольно опы…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →