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

  • 31.10.2019

Отла́дка - этап разработки компьютерной программы , на котором обнаруживают, локализуют и устраняют ошибки. Чтобы понять, где возникла ошибка, приходится:

  • узнавать текущие значения переменных ;
  • выяснять, по какому пути выполнялась программа.

Существуют две взаимодополняющие технологии отладки.

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

Место отладки в цикле разработки программы

Типичный цикл разработки, за время жизни программы многократно повторяющийся, выглядит примерно так:

  1. Программирование - внесение в программу новой функциональности, исправление существующих ошибок .
  2. Тестирование (ручное или автоматизированное; программистом, тестером или пользователем; «дымовое », в режиме чёрного ящика или модульное …) - обнаружение факта ошибки.
  3. Воспроизведение ошибки - выяснение условий, при которых ошибка случается. Это может оказаться непростой задачей при программировании параллельных процессов и при некоторых необычных ошибках, известных как гейзенбаги .
  4. Отладка - обнаружение причины ошибки.

Инструменты

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

Инструменты отладки

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

Также полезными инструментами в руках программиста могут оказаться:

  • Профилировщики . Они позволят определить, сколько времени выполняется тот или иной участок кода. Анализ покрытия позволяет выявить неисполняемые участки кода.
  • API логгеры позволяют отследить взаимодействие программы и Windows API при помощи записи сообщений Windows в лог.
  • Дизассемблеры позволяют посмотреть ассемблерный код исполняемого файла
  • Снифферы помогут отследить сетевой трафик, генерируемый программой
  • Снифферы аппаратных интерфейсов позволяют увидеть данные, которыми обмениваются система и устройство.
  • Логи системы.

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

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

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

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

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

Инструменты, снижающие потребность в отладке

Другое направление - сделать, чтобы отладка нужна была как можно реже. Для этого применяются:

  • Контрактное программирование - чтобы программист подтверждал другим путём, что ему на выходе нужно именно такое поведение программы. В языках, в которых контрактного программирования нет, используется самопроверка программы в ключевых точках.
  • Модульное тестирование - проверка поведения программы по частям.
  • Статический анализ кода - проверка кода на стандартные ошибки «по недосмотру».
  • Высокая культура программирования, в частности, паттерны проектирования , соглашения об именовании и прозрачное поведение отдельных блоков кода - чтобы объявить себе и другим, каким образом должна вести себя та или иная функция.
  • Широкое использование проверенных внешних библиотек.

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

Тестирование программы – это процесс выполнения программы с целью обнаружения ошибки в программе на некотором наборе данных, для которого заранее известен результат применения или известны правила поведения этих программ. Указанный набор данных называется тестовым, или просто тестом. Прохождение теста – необходимое условие подтверждения правильности программы. На тестах проверяется правильность реализации программой запланированного алгоритма. Таким образом, отладку можно представить в виде многократного повторения трех процессов: тестирования, в результате которого может быть констатировано наличие в ПС ошибки, поиска места ошибки в программах и документации ПС и редактирования программ и документации с целью устранения обнаруженной ошибки.

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

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

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

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

Всю документацию можно разбить на две группы:

– документы управления разработкой ПС;

– документы, входящие в состав ПС.

Документы управления разработкой ПС протоколируют процессы разработки и сопровождения ПС, обеспечивая связи внутри коллектива разработчиков и между коллективом разработчиков и менеджерами – лицами, управляющими разработкой.

Пользовательская документация ПС объясняет пользователям, как они должны действовать, чтобы применить данное ПС.

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

Контрольные вопросы

1. Что такое система программирования?

2. Что относится к технологии OLE?

3. Что относится к технологии Microsoft .NET?

4. Что такое модульное программирование?

5. Назовите основные принципы объектно-ориентрованного программирования.

6. Что относится к процедурному программированию?

7. Как происходит отладка и тестирование программ?

8. Какие виды документации используют при разработке программ?

9. Что такое парадигма программирования?

10. Что такое объекты, классы?

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

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

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

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

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

Замечание

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

Первый шаг отладки - это запуск компилятора: Debug > compile <имяПроекта>. Компилятор, просматривая код программы, найдет ошибку и выдаст сообщение: sub or Function not defined (Процедура или функция не определены), выделив место ошибки (creatitem) в теле процедуры.

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

Set tsk = Createltem(olTaskltem)

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

Замечание

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

Запуск программы в VBA осуществляется разными способами. Уже упоминалась возможность запуска программы посредством нажатия клавиши или с помощью команды 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 не активна, она бывает очень полезна в ряде случаев. Например, при прерывании хода программы комбинацией клавиш + только для проверки контрольных значений в окне Immediate, когда нет необходимости переходить в режим отладки, если все значения удовлетворительны. Кнопка End используется для окончательного прерывания хода программы, как правило, когда ошибка сразу видна и не требует отладочных средств.

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

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

В нашем же случае произошла семантическая ошибка: неправильное присваивание переменной значения ссылки на объект. Для устранения этой ошибки необходимо добавить оператор присваивания set перед переменной tsk. Давайте еще раз запустим программу. На этот раз она успешно завершилась, дойдя до конца и выдав сообщение "Задача успешно поручена".

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

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

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

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

Рис. 22.7.

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

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

Замечание

Есть и более простой и, на наш взгляд, естественный способ установки точек останова: достаточно просто сделать щелчок мышью по серой полоске у левого края соответствующей строки кода. Снять эту точку можно повторным щелчком по жирной коричневой точке. Наконец, если вы хотите снять все ранее поставленные точки останова, вовсе необязательно снимать все эти точки поодиночке. Достаточно воспользоваться командой меню > 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 вышеописанным способом. Чтобы наблюдать значение переменной, необходимо выполнить следующее действие.

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

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

{В окне Watch}

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

Expression:= tsk.StartDate

Procedure AssignTask

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

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

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

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

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

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

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

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

Замечание

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

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

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

Команда Назначение
Compile Компиляция программы
Run Sub/UserForm Запуск процедуры или формы
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. Средства отладчика

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

Цель и порядок работы

Цель работы – изучить инструментальные средства и возможности отладки программ в интегрированной среде Microsoft Visual C++ 2008 (Visual Studio 2008).

Порядок выполнения работы:

Ознакомиться с описанием лабораторной работы;

Получить задание у преподавателя, согласно своему варианту;

Написать программу и отладить ее на ЭВМ;

Оформить отчет.

Краткая теория

Интегрированная интерактивная среда разработки программ Microsoft Visual C++ 2008 (IDE) включает в себя ряд средств, облегчающих процесс нахождения ошибок в программе, которые не позволяют ей корректно работать.

Понятие отладки

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

Отладка программы является одним из наиболее важных и трудоемких этапов разработки. Трудоемкость и эффективность отладки напрямую зависит от способа отладки и от средств языка программирования.

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

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

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

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

Разбивайте программу на части: модули, процедуры, функции. Избегайте построения функций, размер которых больше 25-30 строк, в противном случае разбивайте их на несколько меньших по размеру функций;

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

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

Тестирование и отладка программы

Чем больше опыта имеет программист, тем меньше ошибок в коде он совершает. Но, хотите верьте, хотите нет, даже самый опытный программист всё же допускает ошибки. И любая современная среда разработки программ должна иметь собственные инструменты для отладки приложений, а также для своевременного обнаружения и исправления возможных ошибок. Программные ошибки на программистском сленге называют багами (англ. bug - жук), а программы отладки кода - дебаггерами (англ. debugger - отладчик). Lazarus, как современная среда разработки приложений, имеет собственный встроенный отладчик, работу с которым мы разберем на этой лекции.

Ошибки, которые может допустить программист, условно делятся на три группы:

  1. Синтаксические
  2. Времени выполнения (run-time errors)
  3. Алгоритмические

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

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


Рис. 27.1.

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

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

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

Ошибки времени выполнения (run-time errors) тоже, как правило, легко устранимы. Они обычно проявляются уже при первых запусках программы, или во время тестирования . Если такую программу запустить из среды Lazarus, то она скомпилируется, но при попытке загрузки, или в момент совершения ошибки, приостановит свою работу, выведя на экран соответствующее сообщение. Например, такое:


Рис. 27.2.

В данном случае программа при загрузке должна была считать в память отсутствующий текстовый файл MyFile.txt . Поскольку программа вызвала ошибку, она не запустилась, но в среде Lazarus процесс отладки продолжается, о чем свидетельствует сообщение в скобках в заголовке главного меню , после названия проекта. Программисту в подобных случаях нужно сбросить отладчик командой меню "Запуск -> Сбросить отладчик ", после чего можно продолжить работу над проектом.

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

Если программу запустить из самой Windows , при возникновении этой ошибки появится такое же сообщение. При этом если нажать "OK ", программа даже может запуститься, но корректно работать все равно не будет.

Ошибки времени выполнения бывают не только явными, но и неявными, при которых программа продолжает свою работу, не выводя никаких сообщений, а программист даже не догадывается о наличии ошибки. Примером неявной ошибки может служить так называемая утечка памяти . Утечка памяти возникает в случаях, когда программист забывает освободить выделенную под объект память . Например, мы объявляем переменную типа TStringList , и работаем с ней:

begin MySL:= TStringList.Create; MySL.Add("Новая строка"); end;

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

begin MySL:= TStringList.Create; MySL.Add("Новая строка"); ...; //работа с объектом MySL.Free; //освободили объект end;

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

begin try MySL:= TStringList.Create; MySL.Add("Новая строка"); ...; //работа с объектом finally MySL.Free; //освободили объект, даже если была ошибка end; end;

Итак, во избежание ошибок времени выполнения программист должен не забывать делать проверку на правильность ввода пользователем допустимых значений, заключать опасный код в блоки try…finally…end или try…except…end , делать проверку на существование открываемого файла функцией FileExists и вообще соблюдать предусмотрительность во всех слабых местах программы. Не полагайтесь на пользователя, ведь недаром говорят, что если в программе можно допустить ошибку, пользователь эту возможность непременно найдет.

Алгоритмические ошибки

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

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

Если программа работает правильно с одними наборами исходных данных, и неправильно с другими, то это свидетельствует о наличии алгоритмической ошибки. Алгоритмические ошибки иногда называют логическими, обычно они связаны с неверной реализацией алгоритма программы: вместо "+" ошибочно поставили "-", вместо "/" - "*", вместо деления значения на 0,01 разделили на 0,001 и т.п. Такие ошибки обычно не обнаруживаются во время компиляции , программа нормально запускается, работает, а при анализе выводимого результата выясняется, что он неверный. При этом компилятор не укажет программисту на ошибку - чтобы найти и устранить её, приходится анализировать код, пошагово "прокручивать" его выполнение, следя за результатом. Такой процесс называется отладкой .

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