Обновить
Комментарии 14
Да, с отладчиками грустно, даже для C/C++. Если под Windows еще как-то выручает отладчик Visual Studio, то под Linux совсем беда — как с отладчиками, так и с IDE. Да, Qt Creator что-то может, но если редактор там еще нормальный, то отладчик — тоже некая не очень удобная надстройка над древним gdb.

Для C/C++ под Линукс чуть помогает rr, который умеет «отматывать» время назад. В WinDbg Preview тоже такое недавно добавили. Но это только часть необходимых возможностей, конечно.

Clion предоставляет вполне комфортную работу с GDB.
Статья понятна, но не понятно, чего именно не хватает в современном отладчике. А то ощущение, что претензия одна — возраст Горбачева

Если говорить о конкретике, то текста получилось бы еще на пару экранов. :) Основная проблема — это отсутствие поддержки языковых фич, да хотя бы даже парсеров выражений. В lldb, например, для Раста вообще используется парсер выражений от C++, что вызывает серьезные трудности. Если пытаться отлаживать менее прямолинейный код (например, async/await в Расте или код использующий thread-local переменные в C/C++), все эти проблемы начинают копиться как снежный ком, и в итоге получается, что проще вернуться к знакомым println и логам.

А без конкретики ничего не понятно. Я могу предположить, что у меня Си головного мозга, но, например, я не очень представляю что вы хотите получить в итоге.

Если смотреть с точки зрения Си, то, пожалуй, наиболее близкий пример здесь — это BPF, виртуальная машина внутри ядра Линукса, на базе которой, например, делают инструменты трассировки bcc. Через них можете смотреть, какие системные вызовы происходят, какие файлы открываются программой, сколько памяти выделяется (и отслеживать утечки), и т.д. — все это работает похожим на gdb образом, с той разницей, что брейкпоинты ставятся и обрабатываются "автоматически" — т.е., скажем, поставили брейкпоинт на вызов malloc(), и каждый раз, когда он дергается — считаем, сколько памяти выделили и откуда. В конце эту информацию суммируем и показываем пользователю.


Только в случае BPF это все обычно происходит в контексте ядра, а не в user space — но есть и версия BPF VM для юзерспейса, которая позволяет делать похожие штуки. То, что описывается в статье — близко по смыслу и духу к такому подходу, только в более общем направлении и с возможностью не только ставить брейкпоинты, но и читать произвольные области памяти. Как пример, можете посмотреть расширение для VS Code с визуализацией данных.


Да, это все можно делать, взаимодействуя с GDB через консоль или serial API, но это только та часть, которая про работу с процессами и памятью. Вторая же часть — символизация, которая в целом уже больше актуальна для Раста и других языков, т.к. в целом lldb работает в паре с clang и такой острой проблемы с тем же парсером выражений там нет.

print позволяет одновременно наблюдать состояния разных контестов в разные моменты времени. В отладчике сложно выяснить что нибудь типа «какие значения аргумента у этой функции вообще встречались».

Это, а также то, что «точка останова» очень слабо помогает в мультипоточной высококонкурентной среде, особенно если треды зеленые, и их — легион.


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


Тип «обычных» ошибок сильно изменился со времен Горбачева; остановка выполнения просто больше не актуальна. Что прикажете делать в отладчике, если где-то в середине громоздкой обработки данных / вычисления в тысяче потоков, — гонка, которая портит результат?

В случае гонки даже простое добавление/удаление print'а повлияет на итоговый результат.

В случае гонки даже простое добавление/удаление print'а повлияет на итоговый результат.

Безусловно. И что?

«точка останова» очень слабо помогает в мультипоточной высококонкурентной среде, особенно если треды зеленые, и их — легион.

Именно этот сценарий с отладкой зеленых тредов меня и заставил задаться вопросами из статьи. :)


остановка выполнения просто больше не актуальна

По-моему, тут дело в том, что мы воспринимаем отладку как интерактивный процесс, хотя это не обязательно так и не всегда так. "Остановка выполнения" может занимать миллисекунды и происходить автоматически, незаметно для вас. В комментарии выше я приводил примеры с BPF, который по сути тоже является отладчиком и как раз помогает работать с такими сценариями, когда у нас миллионы событий, и среди них надо выцепить нужное и понять, что именно происходит. DTrace в FreeBSD/Solaris решает ту же проблему с помощью специального DSL, позволяющего эффективно фильтровать события, агрегировать их, и выводить нужный результат — и это гораздо удобнее тех же принтов, потому что а) программу не надо перекомпилировать, б) точки трассировки можно добавлять прямо в рантайме в любой процесс (в том числе в продакшене), со сравнительно небольшим оверхедом, в) точки трассировки можно добавлять даже в ядро.

BPF, который по сути тоже является отладчиком

Или «который по сути тоже является принтом» :)


DSL, позволяющего эффективно фильтровать события, агрегировать их, и выводить нужный результат

Я совершенно не чувствую себя компетентным в вопросах именно низкоуровневой отладки со стороны отладчика (да и со стороны пользователя тоже), но мне кажется, что это решение уже ближе к тому, что называется «телеметрия». Отправить асинхронное сообщение в чужой поток, который слушает, получает, фитльтрует, агрегирует, показывает, даже как-то взаимодействует когда надо с основным процессом —  задача несложная, и много где реализованная.


Когда я начинал, мутабельной была куча. И иногда даже стек. Литералли :)
Тут было архиполезно остановить мир, и тщательно изучить байты и заменить условный jmp на безусловный, чтобы отучить глупый Doom проверять ключик.


Потом мутабельными стали только объекты на несколько уровней абстракции выше. Уже там не было большой разницы: красиво развернуть дерево свойств объекта в VS/Netbeans, или просто дампнуть с именами переменных. Ну, поправить на лету было удобнее.


Теперь мутабельность, вроде, почти везде подвергнута анафеме, и по сути «принт», «телеметрия» и «отладка» — превратились примерно в одно и то же: насколько структурированно вы можете выплюнуть объект, чтобы его потом можно было легко проанализировать, классифицировать, привязать.


Зачем бы мне захотелось добавлять трассировку в продакшене я себе представляю слабо, но если захочется — я средствами языка это сделаю на коленке за пять минут. Причем так, что версия без оверхеда вовсе будет собираться просто с другим ключиком. И оно будет проще и надежней, чем любое generic решение.


Но, как я сказал, я могу целых пластов просто не понимать, или даже не видеть.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.