Комментарии 18
Ох уж эта священная война между любителями отладчиков и любителями логов.
Отладчик хорош для простых случаев.
Хотел бы я посмотреть, как вы будете отлаживать отладчиком многопоточный высоконагруженный сервер, который нет, не падает под высокой нагрузкой, но начинает лажать в бизнес-логике.
Я уж не говорю о том, что на целевой платформе может просто и не быть отладчика.
Поэтому нет, отладчик не отменяет структурированных логов (и это не просто, “пишем какую-то фигню в cout”).
И ещё один момент. Когда у вас формируется опыт отладки по логам, вы учитесь структурировать код так, чтобы его поведение было понятным по логам. Это делает ваши решения более прямолинейными, что хорошо и для отладки и в целом, для структурирования кода.
Запускаешь под тред саном, нагружаешь, находишь гонку, дебажишь. Ничего сложного.
Ну допустим, под тред саном проблема не воспроизводится. И тред сан не находит, к чему придраться.
Что дальше будем делать?
так какой у вас аргумент против отладчика? то что сервер высоконагруженный? так себе довод.
Вы рассматривали rr - record repeat дебаггер? Можно однин раз записать то как воспроизводится ошибка, а потом дебажить идентичное исполнение, даже адреса будут такие же. Например, если где-то портятся данные, можно поставить бряк на момент когда они испорчены, поставить watch/бряк на момент записи в них и запустить reverse continue - в итоге последовательно пройтись по моментам когда туда были записаны некорректные данные.
Не считаю что логи бесполезны. Логи нужны и автор статьи этого не отрицал. Он говорил про printf-дебаггинг.
Но то что дебаггер подходит только для простых случаев… большое заблуждение
Как бы так сказать…
Я не возражаю против отладчика, как такового.
Но есть множество ситуаций, когда отладчик, скажем так, малоприменим.
Например, достаточно сложная система с большим количеством параллельных активностей и низкой вероятностью возникновения проблем. Вы запускаете её под отладчиком раз, другой, у вас всё хорошо. А под реальной нагрузкой падает. Даже и не падает, при падении хоть есть стек. Глючит, выдаёт неправильный результат. Сломаное состояние такой системы очень трудно поймать в отладчике.
Другой пример, ваша программа прекрасно работает у вас на компьютере и проходит все тесты. А у заказчика проявляются какие-то ошибки. Приехать к заказчику с отладчиком - не вариант. В лучшем случае вы можете попробовать воспроизвести у себя конфигурацию заказчика. Только вот беда, конфигурацию вы воспроизвели, а у вас всё равно всё хорошо работает. А у него - нет. Куда тут подлезть с отладчиком?
Третий пример, ваша программа прекрасно работает в отладочной сборке. А в релизной - нет. И компилятор так всё соптимизировал, что вы даже и понимаете, куда хотите заглянуть, но отладчик не видит ваших переменных, компилятор их уоптимизировал с глаз долой. Что делать?
Четвёртый пример, ваш код исполняется на встраиваемой системе. Теоретически, там даже и отладчик есть. Только не работает по инструкции. Вы лезете разбираться, и через несколько частов выясняется, что у вас появился новый проект: запустить отладчик на вашей железке. Очевидно непростой, и с малопредсказуемыми сроками исполнения.
Скажете, это редкие случаи? Возможно. Но это зависит от вашего опыта, вашей практики. Как по мне, именно какие-то такие случаи занимают достаточное количество усилий, чтобы хоть запомниться. А те простые случаи, которые берутся с отладчиком, ну они и без него прекрасно берутся.
И вот мысль, которую я хочу подчеркнуть отдельно. Когда основной ваш поиск ошибок происходит в условиях, когда у вас нет доступа к живой системе с отладчиком в руках, вы постепенно приучаетесь структурировать свой код так, что он становится пригоден для такой отладки. Логи в нужных местах, стараетесь не писать в лог всякий шум, события в логах должны быть сводимы, цепочки принятия решений должны отслеживаться. Пользовательскую конфигурацию имеет смысл записать в лог - это экономит время по извлечению её из пользователя (и гарантирует точность). Это влияет на саму логику вашего кода, и влияет в лучшую сторону. Вам приходится заранее хорошо задумываться, что делает ваш код. А не когда уже припёрло.
По-моему, как-то вот так…
И компилятор так всё соптимизировал, что вы даже и понимаете, куда хотите заглянуть, но отладчик не видит ваших переменных, компилятор их уоптимизировал с глаз долой. Что делать?
Смотрим в отладчике ассемблер )
Но соглашусь, что отладчик хорош для исследования крешей. Если просто после долгой обработки результат не сходится - логирование промежуточных данных гораздо полезнее. И аргумент с проблемами на пользовательской машине тоже правильный, и опять же логи хороши. Но при падении на локальной машине в процессе разработки отладчик экономит время.
Не знаю, я прекрасно обхожусь с отладчиком при изучении непонятного поведения многопоточных тяжёлых приложений с openmp на fortran, к примеру. Ну, когда кода ~30к строк и писал не я изначально, логи (они есть) в лучшем случае направление исследования зададут, а в худшем – просто шум. Просто отслеживал интересующие переменные, даже если они очень крупные массивы, локализовал точки отказа...
У меня не было (к счастью) всех перечисленных Вами сценариев, но и свои случаи считать простыми я бы не смог даже с натяжкой. И кстати, просмотр асм кода весьма помогает, да. Оптимизаций ЦП не боюсь совершенно, всё прозрачно, разобраться можно, просто долго.
Да вот пример из собственной практики, в гошном stdlib-е:
https://habr.com/ru/articles/906796/
С точки зрения санитайзера (race detector-а), там всё было хорошо.
Следующий этап это постмортем анализ, а далее техника записи состояния программы с воспроизведением проблемы:
Time Travel Debug - под windows.
RR - под linux.
Но может быть тяжеловесно по размеру дампа.
Хорошая и полезная статья.
А вы пользуетесь отладчиклм из терминала? Есть ли какие-то преимущества над плагиами в ide, для меня вот интерфейс терминала для отладки почти бесполезен и не ускоряет посравнению “отладкой принтами”
Под капотом той же vscode именно gdb и работает в текстовом режиме
Присоединяюсь к комментарию выше. Подскажите, пожалуйста, почему Ваш выбор пал на отладчик в консоли? Почему в статье проигнорированы отладчики, встроенные в IDE?
Мой метод отладки выглядел примерно так
Это называетса принтф-отладка (printf debugging).
Выше уже отметили про "перемотку времени". Представьте, што случился баг, но вы не перезапускаете програму, штобы попытатса повторить и понять баг, и потом начать принт-отладку или подключить отладчик. Вы пошагово исполняете програму назад. И так вы сразу увидите, какое неправильное значение вызывает баг, а отматывая далее вы увидите откуда вообще оно взялось.
Называют такое "Всезнающий отладчик" (omniscient debugger). И я никак не могу понять, почему он не становитса стандартом разработки.
Видимо, потому што их сложно разработать и поэтому на Винде они все платные, нужен аналог rr.

GDB для тех, кто думает, что отладка — это фантастика