Что значит отладить программу программирование

Обновлено: 07.07.2024

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

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

За методами, которые мы показывали до сих пор, стоит неустановленное предположение: как только мы запустим код, он будет работать до завершения (только с паузой для приема входных данных) без возможности вмешаться и проверить результаты программы в любой момент времени, какой мы захотим.

Однако что, если бы мы смогли убрать это предположение? К счастью, мы можем. Большинство современных IDE поставляются со встроенным инструментом, называемым отладчиком, который предназначен именно для этого.

Отладчик

Отладчик – это компьютерная программа, которая позволяет программисту контролировать выполнение программы и проверять ее состояние во время выполнения программы. Например, программист может использовать отладчик для выполнения программы построчно, по ходу проверяя значения переменных. Сравнивая фактические значения переменных с ожидаемыми или наблюдая за ходом выполнения кода, отладчик может существенно помочь в отслеживании семантических (логических) ошибок.

Возможности отладчика двойственные: способность точно контролировать выполнение программы и возможность просматривать (и при желании изменять) состояние программы.

Ранние отладчики, такие как gdb, были отдельными программами с интерфейсами командной строки, где программисту приходилось вводить загадочные команды, чтобы заставить их работать. Более поздние отладчики (такие как ранние версии Turbo Debugger от Borland) всё еще были автономными, но поставлялись со своими собственными «графическими» интерфейсами для облегчения работы с ними. Большинство современных IDE, доступных в наши дни, имеют встроенный отладчик, то есть отладчик использует тот же интерфейс, что и редактор кода, поэтому вы можете отлаживать программу, используя ту же среду, которую вы используете для написания кода (вместо того, чтобы переключаться между программами).

Практически все современные отладчики содержат один и тот же стандартный набор базовых функций, однако единообразия в том, как организованы меню для доступа к этим функциям, нет, и еще меньше единообразия в сочетаниях клавиш. Хотя в наших примерах будут использоваться скриншоты Microsoft Visual Studio (и мы расскажем, как делать всё в Code::Blocks), у вас не должно возникнуть проблем с выяснением того, как получить доступ к каждой обсуждаемой нами функции, независимо от того, в какой среде разработки вы находитесь, даже если вашу IDE, мы не рассматриваем явно.

Остаток этой главы будет посвящен изучению того, как использовать отладчик.

Совет

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

Предупреждение

Прежде чем продолжить этот урок (и последующие уроки, связанные с использованием отладчика), убедитесь, что ваш проект скомпилирован, используя конфигурацию отладочной сборки (для получения дополнительной информации смотрите «0.9 – Настройка компилятора: конфигурации сборки»).

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

Для пользователей Code::Blocks

Если вы используете Code::Blocks, ваш отладчик может быть настроен правильно, а может и нет. Давайте, проверим.

Сначала перейдите в меню Settings (Настройки) → Debugger (Отладчик). Затем откройте дерево отладчика GDB/CDB (GDB/CDB debugger) слева и выберите Default (По умолчанию). Должно открыться диалоговое окно, которое выглядит примерно так:

Рисунок 1 Настройки отладчика в Code::Blocks

Рисунок 1 – Настройки отладчика в Code::Blocks

Если вы видите большую красную полосу на месте Executable path (Путь к исполняемому файлу), то вам нужно найти отладчик. Для этого нажмите кнопку … справа от поля Executable path. Затем найдите файл gdb32.exe в вашей системе – мой был в C:\Program Files (x86)\CodeBlocks\ MinGW\bin\gdb32.exe . Затем нажмите ОК.

Для пользователей Code::Blocks

Пошаговое выполнение

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

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

Есть несколько пошаговых команд, которые мы рассмотрим по очереди.

Шаг с заходом (step into)

Команда шаг с заходом (step into) выполняет следующую инструкцию в обычном пути выполнения программы, а затем приостанавливает выполнение программы, чтобы мы могли проверить состояние программы с помощью отладчика. Если выполняемый оператор содержит вызов функции, шаг с заходом заставляет программу перескакивать в начало вызываемой функции, где она приостанавливается.

Давайте посмотрим на очень простую программу:

Давайте отладим эту программу, используя команду шаг с заходом.

Сначала найдите и затем выполните команду отладки шаг с заходом один раз.

Для пользователей Visual Studio

В Visual Studio к команде шаг с заходом (step into) можно получить доступ через меню Отладка (Debug) → Шаг с заходом (Step Into), или нажав клавишу F11 .

Для пользователей Code::Blocks

В Code::Blocks к команде шага с заходом можно получить доступ через меню Debug (Отладка) → Step into (Шаг с заходом), или нажав Shift + F7 .

Для других компиляторов

Если вы используете другую среду IDE, вы, вероятно, найдете команду step into в меню Debug (Отладка) или Run (Выполнить).

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

  • При необходимости программа перекомпилируется.
  • Программа начинает выполняться. Поскольку наше приложение является консольной программой, должно открыться окно консоли. Оно будет пустым, потому что мы еще ничего не выводили.
  • В вашей IDE могут открываться некоторые диагностические окна, которые могут иметь такие названия, как «Diagnostic Tools» (средства диагностики), «Call Stack» (стек вызовов) и «Watch» (наблюдение). Некоторые из них мы рассмотрим позже – пока вы можете их игнорировать.

Поскольку мы выполнили шаг с заходом, теперь вы должны увидеть какой-то маркер слева от открывающей скобки функции main (строка 9). В Visual Studio этот маркер представляет собой желтую стрелку (Code::Blocks использует желтый треугольник). Если вы используете другую IDE, вы должны увидеть что-то, служащее той же цели.

Рисунок 2 Маркер строки, которая будет выполнена следующей, в Visual Studio

Рисунок 2 – Маркер строки, которая будет выполнена следующей, в Visual Studio

Этот маркер стрелки указывает, что указанная строка будет выполнена следующей. В этом случае отладчик сообщает нам, что следующая выполняемая строка – это открывающая скобка функции main (строка 9).

Выполните шаг с заходом (используя соответствующую команду для вашей IDE, как описано выше), чтобы выполнить открывающую скобку, и стрелка переместится к следующей инструкции (строка 10).

Рисунок 3 Положение маркера после выполнения открывающей фигурной скобки

Рисунок 3 – Положение маркера после выполнения открывающей фигурной скобки

Это означает, что следующая строка, которая будет выполнена, – это вызов функции printValue .

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

Рисунок 4 Положение маркера после выполнения захода в функцию printValue

Рисунок 4 – Положение маркера после выполнения захода в функцию printValue

Выполните шаг с заходом снова, чтобы выполнить открывающую скобку функции printValue , которая переместит стрелку на строку 5.

Рисунок 5 Положение маркера после выполнения следующего шага с заходом

Рисунок 5 – Положение маркера после выполнения следующего шага с заходом

Выполните шаг с заходом снова, который выполнит инструкцию std::cout << value и переместит стрелку в строку 6.

Предупреждение

Поскольку operator<< реализован как функция, ваша IDE может вместо этого перейти к реализации operator<< .

Если это произойдет, вы увидите, как ваша IDE откроет новый исходный файл, а стрелка-маркер переместится в начало функции с именем operator<< (это часть стандартной библиотеки). Закройте только что открытый исходный файл, затем найдите и выполните команду отладки шаг с выходом (step out) (если вам нужна помощь, инструкции приведены ниже в разделе «Шаг с выходом (step out)»).

Теперь, поскольку std::cout << value выполнено, теперь мы должны увидеть, что в окне консоли появилось значение 5.

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

Вы заметите, что стрелка снова указывает на printValue !

Рисунок 6 Положение маркера после завершения функции printValue

Рисунок 6 – Положение маркера после завершения функции printValue

Хотя вы можете подумать, что отладчик намеревается снова вызвать printValue , на самом деле он просто сообщает вам, что он возвращается из вызова функции.

Выполните шаг с заходом еще три раза. На этом этапе мы выполнили все строки в нашей программе, поэтому мы закончили. Некоторые отладчики на этом этапе автоматически завершают сеанс отладки, некоторые – нет. Если ваш отладчик этого не делает, вам может потребоваться найти в меню команду Stop Debugging (остановить отладку) (в Visual Studio это находится в разделе Отладка (Debug) → Остановить отладку (Stop Debugging)).

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

Поздравляем, теперь вы пошагово выполнили программу и наблюдали за выполнением каждой строки!

Шаг с обходом (step over)

Как и шаг с заходом, команда шаг с обходом (step over) выполняет следующую инструкцию в обычном пути выполнения программы. Однако в то время как шаг с заходом будет входить в вызовы функций и выполнять их построчно, шаг с обходом выполнит всю функцию без остановки и вернет вам управление после выполнения этой функции.

Для пользователей Visual Studio

В Visual Studio к команде шаг с обходом (step over) можно получить доступ через меню Отладка (Debug) → Шаг с обходом (Step Over), или нажав клавишу F10 .

Для пользователей Code::Blocks

В Code::Blocks команда шаг с обходом называется Next line (следующая строка), и к ней можно получить доступ через меню Debug (Отладка) → Next line (Следующая строка), или нажав клавишу F7 .

Давайте посмотрим на пример, в котором мы делаем шаг с обходом вызова функции printValue :

Сначала используйте команду шаг с заходом, пока маркер выполнения не окажется в строке 10:

Рисунок 7 Положение маркера перед выполнением функции printValue

Рисунок 7 – Положение маркера перед выполнением функции printValue

Теперь выполните шаг с обходом. Отладчик выполнит функцию (которая выводит значение 5 в окно консоли), а затем вернет управление вам в следующей инструкции (строка 12).

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

Шаг с выходом (step out)

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

Для пользователей Visual Studio

В Visual Studio команду шаг с выходом можно выполнить через меню Отладка (Debug) → Шаг с выходом (Step Out), или нажав комбинацию клавиш Shift + F11 .

Для пользователей Code::Blocks

В Code::Blocks к команде шаг с выходом можно получить доступ через меню Debug (Отладка) → Step Out (Шаг с выходом), или нажав комбинацию клавиш Ctrl + F7 .

Давайте посмотрим на пример этого, используя ту же программу, что и выше:

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

Рисунок 8 Положение маркера в начале выполнения функции printValue

Рисунок 8 – Положение маркера в начале выполнения функции printValue

Затем выполните шаг с выходом. Вы заметите, что в окне вывода появится значение 5, и отладчик вернет вам управление после завершения функции (в строке 10).

Рисунок 9 Положение маркера после выполнения шага с выходом в функции printValue

Рисунок 9 – Положение маркера после выполнения шага с выходом в функции printValue

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

Шагнули слишком далеко

При пошаговом выполнении программы вы обычно можете шагать только вперед. Очень легко случайно перешагнуть то место, которое вы хотели исследовать.

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

Шаг назад

Некоторые отладчики (такие как Visual Studio Enterprise Edition и GDB 7.0) представили возможность пошагового выполнения, обычно называемую шагом назад или обратной отладкой. Цель шага назад – отмотать последний шаг назад, чтобы вы могли вернуть программу в предыдущее состояние. Это может быть полезно, если вы перешагнули цель, или если вы хотите повторно проверить только что выполненную инструкцию.

Реализация шага назад требует большой сложности со стороны отладчика (потому что он должен отслеживать отдельное состояние программы для каждого шага). Из-за сложности эта возможность еще не стандартизирована и зависит от отладчика. На момент написания (январь 2019 г.) ни Visual Studio Community Edition, ни последняя версия Code::Blocks не поддерживают эту возможность. Надеюсь, что в какой-то момент в будущем она попадет в эти продукты и станет доступной для более широкого использования.

Как ни странно, программирование может быть сложным и ошибок может быть очень много. Ошибки, как правило, попадают в одну из двух категорий: синтаксические или семантические/смысловые.

Типы ошибок

Синтаксическая ошибка возникает, когда вы пишете код, который не соответствует правилам грамматики языка C++. Например, пропущенные точки с запятой, необъявленные переменные, непарные круглые или фигурные скобки и т.д. В следующей программе есть несколько синтаксических ошибок:

std : cout < "Hi there; << x; // недействительный оператор (:), незаконченное предложение (пропущено " ) и необъявленная переменная return 0 // пропущена точка с запятой в конце стейтмента

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

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

Иногда это может привести к сбою в программе, например, если делить на ноль:

Либо делать вообще не то, что нужно:

return x - y ; // функция должна выполнять сложение, но выполняет вычитание std :: cout << add ( 5 , 3 ) ; // должно быть 8, но результат - 2

К сожалению, компилятор не ловит подобные ошибки, так как он проверяет только то, что вы написали, а не то, что вы хотели этим сделать.

В примерах, приведенных выше, ошибки довольно легко обнаружить. Но в большинстве программ (в которых больше 40 строк кода), семантические ошибки увидеть с помощью простого просмотра кода будет не так-то и легко.

И здесь нам на помощь приходит отладчик.

Отладчик

Старые дебаггеры, такие как GDB, имели интерфейс командной строки, где программисту приходилось вводить специальные команды для старта работы. Современные дебаггеры имеют графический интерфейс, что значительно упрощает работу с ними. Сейчас почти все современные IDE имеют встроенные отладчики. То есть, вы можете использовать одну среду разработки как для написания кода, так и для его отладки (вместо постоянного переключения между разными программами).

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

Степпинг

Команда "Шаг с заходом"

Команда "Шаг с обходом"

Команда "Шаг с выходом"

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

Давайте рассмотрим очень простую программу:

В Visual Studio, перейдите в меню "Отладка" > "Шаг с заходом" (либо нажмите F11 ):


Если вы используете другую IDE, то найдите в меню команду "Step Into/Шаг с заходом" и выберите её.

Когда вы это сделаете, должны произойти две вещи. Во-первых, так как наше приложение является консольной программой, то должно открыться консольное окно. Оно будет пустым, так как мы еще ничего не выводили. Во-вторых, вы должны увидеть специальный маркер слева возле открывающей скобки функции main(). В Visual Studio этим маркером является жёлтая стрелочка (если вы используете другую IDE, то должно появиться что-нибудь похожее):





Может показаться, будто отладчик намеревается еще раз повторить цикл с функцией printValue(), но в действительности он нам просто сообщает, что он только что вернулся из этой функции.


Таким образом мы полностью остановили сеанс отладки нашей программы.

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

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

  1. Синтаксическая ошибка. Неправильное употребление синтаксических конструкций, например употребление оператора цикла For без то или Next.
  2. Семантическая ошибка. Нарушение семантики той или иной конструкции, например передача функции параметров, не соответствующих ее аргументам.
  3. Логическая ошибка . Нарушение логики программы, приводящее к неверному результату. Это наиболее трудный для "отлова" тип ошибки, ибо подобного рода ошибки, как правило, кроются в алгоритмах и требуют тщательного анализа и всестороннего тестирования.

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

В каждой современной системе программирования существует специальное средство отладки программ — отладчик (debugger), который позволяет в режиме интерпретации установить контрольные точки, выполнить отдельные участки программы и посмотреть результаты работы операторов. Естественно, что редактор Visual Basic имеет подобное средство, с которым мы сейчас и познакомимся. В вышеописанной программе мы специально допустили ошибки, на примере которых и продемонстрируем работу отладчика VBA.

Замечание

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

Итак, допущена синтаксическая ошибка, мы сделали опечатку (вместо createitem ввели creatitem), и компилятор стал расценивать это как вызов процедуры пользователя, которая нигде не объявлена. Быстро исправим эту оплошность, добавив злополучную е в код:

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

Замечание

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

Запуск программы в VBA осуществляется разными способами. Уже упоминалась возможность запуска программы посредством нажатия клавиши <F5> или с помощью команды Run Sub\UserForm меню Run. Однако при таком вызове запускается активная процедура, т. е. процедура, в которой находится курсор. Другим Способом является вызов диалогового окна Macros из меню Tools. В этом окне можно выбрать запускаемую процедуру, не делая ее активной.

Итак, мы запустили программу. Что же происходит? Сразу после запуска появляется диалоговое ОКНО об ошибке: Object variable or With block variable not set (объектная переменная или переменная блока with не определена) и четыре варианта продолжения работы с программой (рис. 22.6):

  1. Continue. Продолжить выполнение программы.
  2. End. Закончить выполнение программы.
  3. Debug. Прервать выполнение программы и перейти в режим отладки.
  4. Help. Вывести подробную справку об ошибке.

Замечание

Хотя в данном случае кнопка Continue не активна, она бывает очень полезна в ряде случаев. Например, при прерывании хода программы комбинацией клавиш <Ctrl>+<Break> только для проверки контрольных значений в окне Immediate, когда нет необходимости переходить в режим отладки, если все значения удовлетворительны. Кнопка End используется для окончательного прерывания хода программы, как правило, когда ошибка сразу видна и не требует отладочных средств.

Рис. 22.6. Диалоговое окно Run-time error '91'

Выберем Debug. В этом случае окно с кодом программы становится активным и в нем выделяется (по умолчанию желтым цветом) оператор, на котором прервалось выполнение программы. Мы выбрали Debug, поскольку имеем достаточно большой опыт и по краткому описанию ошибки можем понять, в чем дело. Но вам мы советуем до определенного момента обращаться за разъяснением к справке, в которой подробно и на примерах описана ошибка, вызвавшая прерывание хода программы.

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

Как видите, все параметры верны, кроме загадочного срока окончания задачи, который истекает через 5 дней, в то время как в диалоговом окне продолжительность проекта была равна 5 месяцам.

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

Сгенерированная задача

Рис. 22.7. Сгенерированная задача

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

Чтобы создать точку останова, следует в отлаживаемой процедуре установить точку ввода в любом месте строки кода VBA, перед выполнением которой вы хотите остановить выполнение процедуры. Затем нужно выбрать команду > Debug > Toggle Breakpoint или просто нажать клавишу <F9>. При этом строка будет выделена коричневым цветом, а на левом поле окна кода появится жирная коричневая точка. Для снятия точки останова нужно еще раз повторить те же действия. Если напротив оператора стоит точка ос танова, это означает, что выполнение программы будет приостановлено перед выполнением этого оператора.

Замечание

Есть и более простой и, на наш взгляд, естественный способ установки точек останова: достаточно просто сделать щелчок мышью по серой полоске у левого края соответствующей строки кода. Снять эту точку можно повторным щелчком по жирной коричневой точке. Наконец, если вы хотите снять все ранее поставленные точки останова, вовсе необязательно снимать все эти точки поодиночке. Достаточно воспользоваться командой меню > Debug > Clear All Breakpoints.

Наши подозрения вызвали следующие места программы, в которых мы и расставили точки останова (рис. 22.8).

  • Инициализация переменной tsk (чему равняется значение по умолчанию).
  • Вызов стандартной функции NOW (действительно ли возвращается текущее время).
  • Установка даты окончания задачи (правильно ли происходит суммирование).

После расстановки точек останова необходимо, как было сказано, указать, значения каких переменных мы хотели бы наблюдать. Естественно, что мы выбрали значения полей tsk.startoate и tsk.DueDate. Для наблюдения за несколькими свойствами или переменными существуют специальные окна Locals Window и Watch Window. Эти окна можно открыть с помощью соответствующих кнопок на панели Debug или команд меню View.

В окне локальных переменных можно наблюдать за значением всех локальных переменных выполняемой в данный момент процедуры, а окно контрольных значений предназначено для постоянного наблюдения за выбранными пользователем переменными или свойствами. Чтобы определить контрольное значение, достаточно выделить в окне модуля любую переменную, выражение или свойство и нажать кнопку Quick Watch на панели инструментов Debug. При этом появится диалоговое окно, в котором указано имя подпрограммы, само выражение, а также его текущее значение (рис. 22.8).

Нажав на расположенную в правой части диалогового окна кнопку Add, можно переместить это выражение в список наблюдаемых контрольных значений в окне Watch. При этом в момент останова отлаживаемой программы весь список наблюдаемых выражений и их значения будут сразу же видны в соответствующем подокне, располагающемся обычно в нижней части экрана. Добавим переменную tsk. star toate вышеописанным способом. Чтобы наблюдать значение переменной, необходимо выполнить следующее действие.

Точки останова и диалоговое окно Quick Watch

Рис. 22.8. Точки останова и диалоговое окно Quick Watch

Пример 22.8. Добавление переменной в окно Add Watch

1R Add Watch. (рис. 22.9)

Итак, точки останова расставлены, окно Add Watch с наблюдаемыми переменными активно, следовательно, с замиранием сердца переходим к трассировке программы. Итак, нажимаем клавишу <F5>, как и предполагалось, перед инициализацией переменной происходит останов программы. Все правильно. Теперь давайте посмотрим, как изменились значения переменных В окне Add Watch: tsk.StartDate = 01:01:4501, tsk.StartDate = 01:01:4501, a duration = 5.

Диалоговое окно Add Watch

Рис. 22.9. Диалоговое окно Add Watch

Для единичного просмотра значения переменной можно просто подвести к ней указатель мыши, и вы увидите всплывающую подсказку. Например, duration = 5.

Для дальнейшего пошагового выполнения программы можно воспользоваться одним из трех способов:

  1. Step Into. При нажатии клавиши <F8> выполняется очередной оператор, после чего выполнение программы приостанавливается и программа становится доступна для корректировки.
  2. Step Over. Нажатие комбинации клавиш <Shift>+<F8> осуществляет вызов вспомогательных процедур и функций за один шаг, что дает возможность не задерживаться на их выполнении.
  3. Step Out. Данная комбинация клавиш <Ctrl>+<Shift>+<F8> позволяет выйти из выполняемой вспомогательной процедуры, не дожидаясь конца ее пошагового выполнения.

Итак, нам необходимо нажать клавишу <F8> и посмотреть, чему стало равно значение tsk.startDate. Как и следовало ожидать, переменной было присвоено значение 21.08.01. (текущая дата 21 августа 2001 года). Следовательно, функция Now работает корректно.

Далее мы попадаем на следующую точку останова — присваивание значения переменной tsk.DueDate. После очередного нажатия клавиши <F8> проверим значения текущих переменных и окончательно обнаружим ошибку.

Значение переменной duration равно 5, прибавляя его к значению текущей даты, мы прибавляем не месяцы (как хотелось бы), а дни. Исправим эту ошибку, изменив код ошибочной строки на следующий:

.DueDate = DateAdd("m", duration, .StartDate)

Замечание

Встроенная функция DateAdd предназначена для добавления или вычитания из даты указанного числа временных интервалов.

В конце рассказа об отладчике мы решили на рис. 22.10 показать панель инструментов Отладка (Debug) с кнопками, используемыми при отладке, а в табл. 22.1 привести краткую справку по всем использованным и неиспользованным средствам отладчика.

Кнопки панели Отладка

Рис. 22.10. Кнопки панели Отладка

Команда Назначение
CompileКомпиляция программы
Run Sub/UserFormЗапуск процедуры или формы
BreakПрерывание выполнения программы <Ctrl>+<Break>
ResetОстановка выполнения программы
Toggle BreakpointsУстановить точку останова
Clear All BreakpointsСнять все точки останова
Step IntoШаг с заходом во вспомогательные процедуры
Step OverШаг с обходом вспомогательных процедур
Step OutШаг с выходом из вспомогательной процедуры
Step to CursorШаг до курсора. Запускает программу на выполнение до строки с курсором
Set Next StatementПозволяет устанавливать следующий выполняемый оператор
Show Next StatementПоказывает следующий выполняемый оператор
Immediate WindowОтображает окно отладочных результатов вычисления
Locals WindowОтображает окно локальных переменных процедуры
Watch WindowОтображает окно контрольных выражений программы
Add WatchДобавляет выражение в окно Watch
Edit WatchИсправляет выражение в окне Watch
Quick WatchПросматривает значение выделенного выражения
Call StackПозволяет показать стек вызовов процедур в текущий момент. Эта кнопка очень полезна при работе с рекурсивными процедурами
Comment BlockПозволяет закомментировать выделенный блок операторов
Uncomment BlockОтменяет сделанные комментарии
Toggle BookmarksУстанавливает закладку
Clear All BookmarksСнимает все установленные закладки
FindВызывает диалоговое' окно поиска, посредством которого можно найти ту или иную переменную, выражение и т. д.

Таблица 22.1. Средства отладчика

К сожалению, не все приемы отладки можно рассмотреть на нашем простейшем примере.

В предыдущей части мы рассмотрели исходный код и его составляющие.

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

Отладка программы

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

Для начала необходимо рассортировать общие ошибки, которые могут возникнуть в исходном коде.

отладка программы

Синтаксические ошибки

Эти эрроры не позволяют скомпилировать исходный код на компилируемых языках программирования. Они обнаруживаются во время компиляции или интерпретации исходного кода. Они также могут быть легко обнаружены статическими анализаторами (линтами). Подробнее о линтах мы узнаем немного позже.

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

Семантические ошибки

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

Рассмотрим данный пример:

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

3 + 5, заключенные в скобки, дадут желаемый результат, а именно 48.

Ошибки в процессе выполнения

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

Вот хороший пример:

Фрагмент кода выше будет скомпилирован успешно, но input 25 приведет к ZeroDivisionError. Это ошибка во время выполнения. Другим популярным примером является StackOverflowError или IndexOutofBoundError. Важно то, что вы идентифицируете эти ошибки и узнаете, как с ними бороться.

Существуют ошибки, связанные с тем, как ваш исходный код использует память и пространство на платформе или в среде, в которой он запущен. Они также являются ошибками во время выполнения. Такие ошибки, как OutOfMemoryErrorand и HeapError обычно вызваны тем, что ваш исходный код использует слишком много ресурсов. Хорошее знание алгоритмов поможет написать код, который лучше использует ресурсы. В этом и заключается отладка программы.

Процесс перезаписи кода для повышения производительности называется оптимизацией. Менее популярное наименование процесса – рефакторинг. Поскольку вы тратите больше времени на кодинг, то должны иметь это в виду.

Отладка программы

Вот несколько советов о том, как правильно выполнять отладку:

  1. Использовать Linters. Linters – это инструменты, которые помогают считывать исходный код, чтобы проверить, соответствует ли он ожидаемому стандарту на выбранном языке программирования. Существуют линты для многих языков.
  2. Превалирование IDE над простыми редакторами. Вы можете выбрать IDE, разработанную для языка, который изучаете. IDE – это интегрированные среды разработки. Они созданы для написания, отладки, компиляции и запуска кода. Jetbrains создают отличные IDE, такие как Webstorm и IntelliJ. Также есть NetBeans, Komodo, Qt, Android Studio, XCode (поставляется с Mac), etc.
  3. Чтение кода вслух. Это полезно, когда вы ищете семантическую ошибку. Читая свой код вслух, есть большая вероятность, что вы зачитаете и ошибку.
  4. Чтение логов. Когда компилятор отмечает Error, обязательно посмотрите, где он находится.

Двигаемся дальше

Поздравляем! Слово «ошибка» уже привычно для вас, равно как и «отладка программы». В качестве новичка вы можете изучать кодинг по книгам, онлайн-урокам или видео. И даже чужой код вам теперь не страшен :)

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

Читайте также: