Что такое отладчик и как он может помочь мне в диагностике проблем?

101

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

Этот вопрос охватывает три класса более конкретных вопросов:

  • Когда я запускаю свою программу, она не дает результата, который я ожидал от введенных мной данных.
  • Когда я запускаю свою программу, она вылетает и дает мне трассировку стека. Я изучил трассировку стека , но до сих пор не знаю причины проблемы, потому что трассировка стека не предоставляет мне достаточно информации.
  • Когда я запускаю свою программу, она дает сбой из-за ошибки сегментации (SEGV).
Raedwald
источник
3
Хорошая работа - также было бы хорошо иметь соответствующие вопросы и ответы на вопросы по методам отладки , например, с использованием отладчика, других инструментов отладки (например, valgrind), стратегических printfs, стресс-тестирования, разделяй и властвуй и т. Д.
Пол R
1
Я согласен с @PaulR, в FAQ должны быть такие вещи.
Нику Стюрка

Ответы:

65

Отладчик - это программа, которая может проверять состояние вашей программы во время ее выполнения. В технических средствах , которые он использует для этого не важны для понимания основы того , как использовать отладчик. Вы можете использовать отладчик, чтобы остановить выполнение вашей программы, когда она достигнет определенного места в вашем коде, а затем проверить значения переменных в программе. Вы можете использовать отладчик для очень медленного запуска вашей программы, по одной строке кода за раз (это называется пошаговым выполнением ), пока вы проверяете значения его переменных.

Использование отладчика - ожидаемый базовый навык

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

Как отладчик может вам помочь

С помощью отладчика вы можете определить, имеет ли переменная неправильное значение и где в вашей программе ее значение изменилось на неправильное.

Используя пошаговое выполнение, вы также можете определить, соответствует ли поток управления ожидаемому. Например, ifвыполняется ли ветвь, когда вы ожидаете, что это должно быть.

Общие примечания по использованию отладчика

Специфика использования отладчика зависит от отладчика и, в меньшей степени, от языка программирования, который вы используете.

  • Вы можете присоединить отладчик к процессу, уже выполняющему вашу программу. Вы можете сделать это, если ваша программа зависла.

  • На практике часто проще запустить вашу программу под управлением отладчика с самого начала.

  • Вы указываете, где ваша программа должна прекратить выполнение, указав файл исходного кода и номер строки той строки, на которой выполнение должно остановиться, или указав имя метода / функции, на которой программа должна остановиться (если вы хотите остановиться как как только исполнение входит в метод). Технические средства, которые отладчик использует для остановки вашей программы, называются точкой останова, а этот процесс называется установкой точки останова .

  • Большинство современных отладчиков являются частью IDE и предоставляют удобный графический интерфейс для изучения исходного кода и переменных вашей программы с интерфейсом «укажи и щелкни» для установки точек останова, запуска вашей программы и пошагового ее выполнения.

  • Использование отладчика может быть очень трудным, если исполняемый файл программы или файлы байт-кода не содержат информацию об отладочных символах и перекрестные ссылки на исходный код. Возможно, вам придется скомпилировать (или перекомпилировать) вашу программу немного иначе, чтобы гарантировать наличие информации. Если компилятор выполняет обширную оптимизацию, эти перекрестные ссылки могут сбивать с толку. Поэтому вам, возможно, придется перекомпилировать вашу программу с отключенной оптимизацией .

Raedwald
источник
4
Это неполно, так как он пропускает самый важный отладчик из всех, который потенциально может значительно сократить количество вопросов по Stackoverflow (я прогнозирую как минимум на 20%) - отладчики javascript: firebug, Chrome, Firefox, IE9 + интегрированный отладчик , IE8 - Visual Studio и т. Д.
slebetman
1
Также для node.js - инспектор узлов. Но программисты node.js не задают столько основных вопросов и / или вопросов, связанных с исправлением кода, как обычные программисты javascript.
слебетман
38

Я хочу добавить, что отладчик не всегда является идеальным решением и не всегда должен быть подходящим решением для отладки. Вот несколько случаев, когда отладчик может не работать:

  • Часть вашей программы, которая терпит неудачу, действительно велика (возможно, плохая модульность?), И вы не совсем уверены, с чего начать пошаговое выполнение кода. Прохождение всего этого может занять слишком много времени.
  • Ваша программа использует множество обратных вызовов и других методов нелинейного управления потоком, что сбивает с толку отладчик, когда вы проходите через него.
  • Ваша программа многопоточная. Или, что еще хуже, ваша проблема вызвана состоянием гонки.
  • Код, в котором есть ошибка, запускается много раз, прежде чем выйдет из строя. Это может быть особенно проблематично в основных циклах или, что еще хуже, в физических движках, где проблема может быть числовой. Даже установка точки останова в этом случае просто заставит вас ударить ее много раз, а ошибка не появится.
  • Ваша программа должна работать в режиме реального времени. Это большая проблема для программ, которые подключаются к сети. Если вы установите точку останова в своем сетевом коде, другой конец не будет ждать, пока вы перейдете, он просто истечет. Программы, которые полагаются на системные часы, например, игры с пропуском кадров, тоже не намного лучше.
  • Ваша программа выполняет некоторую форму деструктивных действий, таких как запись в файлы или отправка электронной почты, и вы хотели бы ограничить количество раз, которое вам нужно запускать через нее.
  • Вы можете сказать, что ваша ошибка вызвана неверными значениями, поступающими в функцию X, но вы не знаете, откуда эти значения. Необходимость запускать программу снова и снова, устанавливая точки останова все дальше и дальше назад, может быть огромной проблемой. Особенно, если функция X вызывается из многих мест по всей программе.

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

Итак, каковы альтернативы?

Самый простой - это просто регистрация и утверждения. Добавьте журналы в свою программу в различных точках и сравните то, что вы получите, с тем, что вы ожидаете. Например, посмотрите, вызывается ли функция, в которой, по вашему мнению, есть ошибка. Посмотрите, соответствуют ли переменные в начале метода тем, о чем вы думаете. В отличие от точек останова, это нормально, если в журнале есть много строк, в которых ничего особенного не происходит. После этого вы можете просто просмотреть журнал. Как только вы попадете в строку журнала, которая отличается от ожидаемой, добавьте еще в той же области. Сужайте его все дальше и дальше, пока он не станет достаточно маленьким, чтобы можно было регистрировать каждую строку в области с ошибками.

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

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

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

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

SlugFiller
источник
9
Это был бы хороший ответ ... на другой вопрос. Это плохой ответ на этот вопрос. Возможно, вам стоит задать этот вопрос и опубликовать его в качестве ответа на него.
Raedwald
7
Фактический вопрос описывается как «помочь новым программистам, у которых возникла проблема с программой», «она не дает ожидаемого вывода» и «я изучил трассировку стека, но все еще не знаю причину проблемы» . Всем этим помогает этот ответ. Кроме того, при объяснении того, что делает отладчик, не менее важно объяснить, чего он не делает.
SlugFiller
5
Отличный ответ. Я всегда использовал отладчик как основной инструмент для поиска ошибок. Но теперь я работаю над проектом, в котором огромный компонент инфраструктуры использует много потоков и много сетевого кода (клиент / сервер), и замечаю, что отладчик - последнее, что мне помогает. Вы упомянули много вещей, в которых вам действительно стоит использовать другой инструмент вместо того, чтобы полагаться на старый добрый отладчик (самое важное: ведение журнала).
Тим
«Вы можете сказать, что ваша ошибка вызвана неправильными значениями, поступающими в функцию X, но вы не знаете, откуда эти значения берутся». Это особенно сложно отладить. Как вы обычно исправляете что-то подобное?
Ayxan Haqverdili
2
@Ayxan В некоторой степени, если вам удалось прервать выполнение функции при утверждении, вы можете использовать стек вызовов, чтобы получить вызывающего. Но это само по себе не дает вам источника значения, потому что значение, скорее всего, взято из более ранней строки. По сути, вы должны проследить за значением через различные переменные, через которые оно проходит. Если у вас есть хорошее представление о пути, по которому идут данные, вы можете просто создать кучу распечаток журнала и попытаться сузить область, где «идет не так». В противном случае вам потребуется отдельный запуск программы (воспроизведение ошибки) для каждого шага назад.
SlugFiller