Я думаю, что необходимо смочь считать имя/значение в Вашем ПОЛУЧАТЬ массив. Я думаю, что кнопка, которая не была нажатой привычкой, появляется в том списке.
Давайте не будем забывать о valgrind ... он не раз спасал мне жизнь, помогая обнаружить непонятное одноразовое повреждение памяти или ошибку неинициализированного значения.
Режим Emacs gud-gdb - это армейский швейцарский нож!
Я больше не поддерживаю режим консоли GDB, я знаю, кто поддерживает, но в моем случае использование отладчика с графическим интерфейсом, когда это возможно, того стоит.
IDA PRO - это еще одна вещь, я тоже могу использовать ее время от времени. время, когда дело доходит до (RE)
Если вы используете отладчик Visual Studio (я подозреваю, что вы это делаете, поскольку вы упомянули «редактировать и продолжить»), вы можете эффективно использовать «Немедленное окно». Вы можете быстро вызвать его с помощью сочетания клавиш Ctrl + Alt + I
«Немедленное окно» довольно близко похоже на цикл «Чтение-Оценка-Печать», который является обычным для динамических языков, но почти отсутствует в C ++ и подобные языки. Непосредственное окно позволит вам оценивать простые выражения, которые вы также можете делать в окне наблюдения, но также позволяет вам запускать простые операторы, для которых окно наблюдения не так хорошо.
Если есть какая-то гипотеза, вы хотите исследуйте во время отладки, выполнение экспериментов в непосредственном окне часто может быстро дать вам ответы. Ты не Не нужно заранее знать, что вам нужно напечатать, вы будете иметь всю необходимую информацию о состоянии, пока вы работаете в отладчике. И вы можете изменить состояние своей программы, выполнив простые операторы, чтобы проверить свою гипотезу, чего нельзя было сделать с помощью простых операторов печати.
Отладка таким способом имитирует инкрементный стиль программирования, популярный в языках, предлагающих REPL. прямо из коробки (например, Python или Ruby). Это может быть весьма полезно при отладке.
Такой способ отладки имитирует инкрементный стиль программирования, популярный в языках, которые предлагают REPL из коробки (например, Python или Ruby). Это может быть весьма полезно при отладке.
Такой способ отладки имитирует инкрементный стиль программирования, популярный в языках, которые предлагают REPL из коробки (например, Python или Ruby). Это может быть очень полезно при отладке.
Пишу осторожно, поэтому я в первую очередь минимизирую создание ошибок.
Когда у меня есть ошибки, я предпочитаю IDE и пошаговое выполнение кода.
Printfs - чрезвычайно мощный инструмент, но по-прежнему оружие последней инстанции.
Наряду с ведением журнала нам помог полезный метод - выгрузка всех полезных переменных в удобочитаемом виде по запросу. Таким образом вы сможете сузить круг возможных причин.
Утверждения. Когда я пишу код, если я замечаю какие-либо крайние случаи, которые, по моему мнению, могут указывать на проблему, я могу добавить строку, которая сообщит мне в отладочных сборках, если такое происходит. За бонусные баллы они не влияют на производительность сборок выпуска, поэтому вы можете проверить полудорогие вещи, например, assert (someMap.find (someKey)! = SomeMap.end ());
Очевидно, они не заменяют проверку реальных условий ошибки, которые вы должны уловить, но они отлично подходят для таких крайних случаев когда вы думаете: «Может, мне стоит это проверить?», пока пишете код.
ASSERTs ASSERTs.
У меня есть 300000 loc (не считая комментариев) сильно разложенного и повторно используемого кода в моих личных библиотеках, из которых около 15% (предположение) - шаблоны, а 50000 loc - тестовый код.
Если идиома дублируется, то она сделана функция / метод. Лично я рассматриваю простоту вырезания и вставки, поскольку изобретение DEVIL намеренно помещено туда, чтобы раздувать код и распространять дефекты.
Около 4% библиотеки - это ASSERTS и отладочный код (очень мало printfs и почти весь вывод является поставленный в очередь вывод в настраиваемую задачу с низким приоритетом потока cout, потому что ввод-вывод экрана настолько дорог и, следовательно, меняется время). Возможно, 50% утверждений предназначены для гарантии инвариантов класса и условий публикации при выполнении метода.
Я беспощадно реорганизовываю код, когда пересматриваю фрагмент кода, который я мог поспешить или, может быть, просто сделал ошибку в дизайне связи интерфейса / объекта, например, объект-субъект метода действительно принадлежит как объект-объект, а метод принадлежит к один из исходных объектов-объектов (объектов-параметров). Либеральный подход к утверждениям, кажется, защитит меня от некоторых глупых ошибок, если я сделаю существенный рефакторинг. Это случается редко, но бывают случаи.
У меня есть макрос DEBUGGING, который действует так же, как ASSERT, поэтому я могу иметь код, окруженный
DEBUGGING (... code ....);
и он не компилируется в неотладочных сборках.
Я не использую assert, поставляемый поставщиком. Мои утверждения НЕ прерывают работу и дамп ядра, они просто вызывают окно сообщения и вызывают отладчик. Если это новый код, а метод - метод const, возможность вернуться к методу, а затем повторно выполнить его (метод) с тем же набором параметров, очень полезна. Иногда даже тот факт, что некоторые данные изменены, не имеет отношения к проблеме, и можно повторно вызвать их с получением знаний.
Я абсолютно НЕНАВИЖУ отладчики командной строки. Это как вернуться на 25 лет назад - с таким же успехом можно использовать телетайп и линию со скоростью 2400 бод. Мне нужна полноценная IDE, в которой можно щелкнуть правой кнопкой мыши по структуре данных и открыть ее, закрыть, выполнить поиск указателей, выполнить методы и т. Д. И т. Д.
Я просматриваю каждую строку моего нового кода и проверяю каждую из моих) переменных для ожидаемого поведения. Здесь бесценно использование IDE, выделяющего изменения. Для этого с GDB нужно быть концертным пианистом, помнящим Карнака Великолепного ;-).
Для новых разработок я также пытаюсь захватить данные потока / данные сообщений при возникновении ненормального состояния. Это особенно полезно для серверов udp и часто дает фору воспроизводимости.
Мне также нравятся симуляторы, которые могут «окружать приложение, управлять им, потреблять от него и выполнять проверку» (объединенные / связанные симуляторы источника / приемника). ) Почти весь мой код безголовый или, по крайней мере, взаимодействие человека не имеет отношения к функциональности, поэтому часто возможно "окружение" приложения. Я считаю очень важным иметь хорошую поддержку и руководство, которое понимает, что создание тестовых данных очень важно а сбор тестовых данных - это то, что складывается в набор тестов, которые могут развиться в комплексный регрессионный / дымовой тест.
Мне также нравилось снижать квантовое планирование ОС. С многопоточными приложениями такие короткие кванты могут легче выявлять ошибки потоковой передачи. Мне особенно нравится управлять потокобезопасными объектными методами с большим количеством потоков - десятками, если не сотнями. В общем, потокобезопасный объект нельзя протестировать на месте , если приложение управляется человеком - просто невозможно им управлять. Таким образом, существует реальная потребность в настраиваемых тестовых драйверах гораздо более низкого (компонентно-ориентированного) уровня. И именно в этом тесте утверждения могут сообщить вам, если что-то сломалось. Очевидно, это не доказывает правильность кода, но дает некоторую уверенность.
Верно также и то, что эти предпочтения, вероятно, отражают представления и роли, в большей степени ориентированные на библиотеки классов / повторное использование, которые у меня были. Когда вы пишете код библиотеки, обычно мало "производственных" проблемы, так как библиотека по определению активно используется и тщательно тестируется. Ведение журнала и подобная история, похоже, больше ориентированы на приложения, чем на библиотеки.
Для этого мне придется пойти с намеренным структурированием проекта, чтобы минимизировать время инкрементной сборки / итерации. В качестве побочного эффекта, это те же шаги, которые необходимы для правильной работы функции редактирования и продолжения.
Прослеживание, изменение переменных в памяти для попадания в какую-то непонятную ветвь кода. Редко редактируйте и продолжайте, по какой-то причине я не могу полностью доверять ему в поддержании нормального состояния, поэтому после изменения выполняется полное выполнение.
Когда невозможно отследить (например, gdb в Windows слишком медленный, для достижения точки останова требуется 30 секунд каждый раз), затем printf. Нежелательный код и сбрасывает время в случае ошибок многопоточности, но иногда это единственный выход.
Отладчики дизассемблера при отладке сборок выпуска без отладочной информации (Olydbg хорош, когда он работает).
Правильное ведение журнала - это хорошо. когда он доступен, требует усилий для настройки и использования, но очень ценен при необходимости.
Отправка трассировки стека сбоев домой еще приятнее.
Утверждения распространяются там, где это необходимо.
Минидампы для сбоев на машинах пользователей.
Занимаясь многопоточностью, я не мог жить без регистрации. Для ведения журнала в C ++ я использую библиотеку templog . Он позволяет несколько уровней серьезности ( насколько это плохо? ) умножить на несколько целей журнала (, кому это может быть интересно? ) в сочетании с таким же количеством приемников журнала фильтрации ( куда писать в? ) как хотите, чтобы не утонуть в шуме. Он имеет большое значение для повышения эффективности, используя мета-шаблон, чтобы помочь компилятору избавиться от лишнего кода, не попадая в ловушку assert (do_something_important ())
.
Кроме того, он достаточно мал (я думаю, что он ниже 1kLoC, разбросанный по полдюжине заголовков) и поставляется с разрешающей лицензией на ускорение, чтобы вы не зависели от создателей, чтобы не упустить мяч. Если они это сделают - вы можете просто поддерживать это самостоятельно.
Я только хочу, чтобы ребята, наконец, превратили эту ветку, в которой находится текущий код, в новый ствол.
Я голосую за gdb. Особенно, когда все, с чем вам нужно работать, - это файл ядра.
printf удобны, когда вы имеете общее представление о том, где находится ошибка. Но когда группа тестирования вернется к вам с файлом ядра и странным описанием проблемы, возможность анализа дампа ядра даст вам огромную фору в ваших усилиях по отладке.
Мне нравится gdb - обычно я использую его в режиме командной строки, но, если вы этого не выносите, для него есть интерфейсы с графическим интерфейсом, например Insight , Ddd и т. Д. Журналы тоже всегда помогают, как и файлы дампа ядра, для которых вы можете выполнить «посмертную отладку» с помощью тех же инструментов.
Реактивные меры:
Использование хорошего отладчика , особенно интегрированного. Используйте отладчик, который визуально работает с вашим кодом.
Тактика отладки. Знакомство с вашими инструментами. Знание распространенных ошибок. Процесс дедукции. Использование гипотез и разветвлений по различным идеям ... возвращение к предыдущим идеям при необходимости. Отслеживание прогресса отладки. Научный метод.
Аналитические инструменты (например, Dependancy Walker , .NET Reflector ), дампы памяти, трассировки стека и журналы.
Профилактические меры:
Небольшие дополнительные строит. Во время активной разработки добавляйте в свой проект по частям и тестируйте каждую входящую часть. Не выкладывайте кучу кода, а затем смешивайте Run и беспечно исправляйте каждую ошибку. Добавляйте в свою программу по частям и не торопитесь, чтобы все исправить. Постарайтесь сделать каждое приращение в вашем проекте «атомарным».
Многоуровневое ведение журнала, как уже указывали другие. Сделайте шкалу серьезности от трассировки до фатальной ошибки и всего, что между ними. Ваше производственное приложение должно регистрировать все, что оно делает, и почему оно было успешным или неудачным, но вы также должны иметь возможность изменять уровень ведения журнала, когда крайний уровень детализации не требуется. Журналы должны быть удобочитаемы в первую очередь.
Отказоустойчивое ведение журнала. Не полагайтесь на свой механизм ведения журнала, чтобы пережить исключительные ситуации. Всегда имейте запасной план - журнал событий, простой текстовый файл, последнее письмо по электронной почте - на случай, когда дела пойдут вверх.
Хорошая политика контроля версий. Как минимум частые заезды по расписанию, плюс проверки всех групп изменений, особенно широко распространенных или потенциально критических изменений.
В общем, printf's. Они позволяют легко нарезать программы и не требуют никаких инструментов, кроме редактора и компилятора.
Многоуровневые системы регистрации. Я использую как минимум 5 уровней:
подробный : вещи, которые вы хотите видеть только при отладке низкоуровневых вещей, таких как ошибки протокола; могут быть скомпилированы из двоичных файлов выпуска, поэтому вы можете поместить на этот уровень вещи, которые не хотите, чтобы конечные пользователи находили
internal : трассировка более низкого уровня, чем нормальный уровень, что часто бывает полезно, но не так часто, что вы хотите видеть это все время
нормальный : уровень вывода по умолчанию, полезный для всех, кто наблюдает за нормальной работой системы
проблема : ошибки времени выполнения, которые программа знает, как справиться; вы можете выбрать запуск на этом уровне для выпускных версий вместо нормальной
фатальной ошибки : сообщения типа «крикни и умри», наподобие нехватки памяти
Многоуровневое ведение журнала позволяет встроить в программу большое количество информации для регистрации, не просматривая ее все время. Вы повышаете уровень журнала только тогда, когда вам нужно что-то отладить, а затем возвращаете его на нормальный уровень. При отладке типа «printf» - временные сообщения - я помещаю их на нормальный уровень, поэтому мне не нужно поднимать уровень журнала, чтобы увидеть их, и чтобы они были скрыты за шумные внутренние или подробные сообщения уровня.
При написании кода подумайте, как вы собираетесь размещать там точки останова позже. В частности, это означает не переусердствовать с вызовами вложенных функций - foo (bar (baz))
- и то же самое для цепочек полей / методов - foo (). Bar (). Baz ()
. В общем, если выражения не являются тривиальными, часто имеет смысл помещать их в отдельные строки и назначать их переменным, даже если значения используются только один раз - затем вы можете легко пройти через каждое, установить точку останова точно там, где вы хотите, и у вас будут значения в окне просмотра. При компиляции с оптимизацией любые такие переменные, вероятно, будут оптимизированы, особенно если вы используете трюк с константной ссылкой вместо того, чтобы полагаться на RVO.
Если моя программа слишком велика, я логически разделяю проблемную часть и отлаживаю ее независимо. Это также дает возможность сделать код более модульным
Одним из наиболее эффективных способов отладки серверного кода IMO является Дифференциальная отладка , то есть сравнение двух файлов журнала.
Это особенно полезно с устаревшим кодом, когда нынешние разработчики не знают всех областей кода. Это помогает сузить область поиска и код, который необходимо проанализировать. Это действительно требует наличия хорошей регистрации / трассировки.
Это работает, когда у вас есть успешный вариант использования, а другой - неудачный. Например, функция X раньше работала в версии 3 вашего продукта, но теперь не работает в версии 4, и никто не знает почему.
Сравните журналы, используйте awk или sed для исключения избыточных различий (эти сценарии можно использовать повторно):
Когда вы видите, что логи расходятся, обычно это указывает на то, что непосредственно перед этим было принято неправильное решение.
Я использовал эту технику для замены проприетарного решения промежуточного программного обеспечения в устаревшей системе на CORBA и убедился, что я не изменил поведение логики приложения. Но это очень полезно во многих ситуациях.
Я использую команду gdb command
для создания операторов printf на лету. Просто убедитесь, что последняя команда - continue.
#assume two breakpoints, 1 and 2
commands 1
silent
echo calling baz\n
set $print_foobar=1
continue
end
commands 2
silent
echo calling foobar\n
if $print_foobar
set $print_foobar=0
backtrace
end
continue
end
Недавно я влюбился в эту технику, поскольку она позволяет мне создавать оператор printf ()
для уже выполняемого кода. Кроме того, сценарии GDB, хотя и ограниченные, позволяют вам многое сделать при принятии решения, что печатать. Я еще не встречал ситуации, когда раздел команд был бы не так хорош или лучше, чем printf ()
.
printf ()
. Кроме того, сценарии GDB, хотя и ограниченные, позволяют вам многое сделать при принятии решения, что печатать. Я еще не встречал ситуации, когда раздел команд был бы не так хорош или лучше, чем printf ()
.