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

Чтобы полноценно работать со стандартными трейсами, нужно знать несколько вещей:

✅ Чтобы фича заработала с новыми версиями gcc и clang, вам нужно залинковать либу -lstdc++exp. В туториалах обычно используется линковка с -lstdc++_libbacktrace, которая не работает на свежих версиях компиляторов

✅ Собирайте код с дебаг символами. Если хотите видеть трейсы и получать из них полезную информацию об именах функций и файлов, вместо прочтения чистых адресов, то надо собирать в дебаге. Итого полная команда сборки:

g++ -std=c++23 -g -lstdc++exp -O2 main.cpp -o app


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

✅ Дебаг символы обычно занимают довольно внушительный объем и не всегда хочется их тянуть везде вместе с бинарем. В таких случаях можно использовать утилиту strip и вырезать из бинаря отдельный файл с дебаг символами. При обнаружении проблемы с программой можно в дебаггере подгрузить файл с символами и наслаждаться прелестями человекочитаемой отладки.

Ну или можно собирать код с флагом -g1, который включает только самую необходимую отладочную информацию

✅ Мы рассматривали стектрейсы в разрезе исключений, но их конечно же можно использовать и отдельно от них.

int foo(int a, int b) {
if (b == 0) {
LOG_ERROR << "Second operand is zero. Trace:\n" << std::stacktrace::current();
}
return a / b;
}


Однако стоит помнить, что получение трейса - не бесплатная штука. Логи-то не бесплатный, а проход по стеку вызовов и сбор информации из дебаг символов - очень затратная штука. Не стоит использовать трейсы в нагруженных частях программы. Только в ошибочных путях программы в некритичном коде.

✅ Сам класс стектрейсов предоставляет много гибкости. Можно отдельно проходиться по каждому фрейму и в принципе контролировать количество захватываемых фреймов:

void inspectTrace(const std::stacktrace& trace) {
for (const auto& frame : trace) {
std::cout << "Function : " << frame.description()
<< '\n'
<< "Source file : " << frame.source_file()
<< '\n'
<< "Line : " << frame.source_line()
<< '\n'
<< "---\n";
}
}

// Capture at most 10 frames except of the last one.
auto trace = std::stacktrace::current(/skip=/1, /max_depth=/10);


Трейсы скорее всего рано или поздно заедут в каком-то виде в стандарт, чтобы их можно было использовать со стандартными исключениями и конктейнерами. Поэтому полезно же сейчас понимать, как это работает под капотом и как этим правильно пользоваться.

Know your origin. Stay cool.

#cpp23
  • 🔥 12
  • ❤ 7
  • 👍 4
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. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
  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 →