Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СПО юнита 2.doc
Скачиваний:
38
Добавлен:
17.11.2019
Размер:
5.82 Mб
Скачать

4.3 Отладка программ в системе Delphi 7

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

Синтаксические ошибки обнаруживаются компилятором автоматически. Сообщения о найденных ошибках отображаются в нижней части редактора (рисунок 26).

Рисунок 26. Информация о синтаксической ошибке, обнаруженной компилятором

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

Undeclared identifier: 'X'.

В данном случае указано, что идентификатор X не объявлен.

Логические ошибки

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

За наиболее часто встречающимися ошибками можно заставить следить саму программу. Для этого в настройках проекта соответствующее диалоговое окно вызывается командой Project > Options (Проект > Настройки). На вкладке Compiler (Компилятор) надо выполнить следующие действия (рисунок 27).

Рисунок 27. Настройка компилятора для максимального контроля ошибок

На панели Code generation (Генерация машинного кода) сбросьте флажок Optimization (Оптимизация). Когда компилятор создает оптимизированный код, он вносит существенные улучшения в детали алгоритма, реализованного на Паскале. Например, если программист вводит в процедуре локальную переменную X для хранения промежуточных результатов

function Sum: integer;

var X: integer;

begin

X := StrToInt(Editl.Text) + StrToInt (Edit2.Text);

Result := X

end;

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

Result := StrToInt(Editl.Text) + StrToInt(Edit2.Text);

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

На панели Runtime errors (Ошибки времени выполнения) должны быть установлены флажки Range checking (Контроль выхода индекса за границы массива), I/O Checking (Контроль ошибок ввода/вывода) и Overflow checking (Контроль переполнения при целочисленных операциях).

На панели Debugging (Отладка) установите флажки Debug information (Добавление отладочной информации), Local symbols (Просмотр значений локальных переменных), Reference info (Просмотр структуры кода), Assertions (Включение процедуры Assert в машинный код) и Use Debug DCUs (Использование отладочных версий стандартных модулей библиотеки компонентов VCL). Без отладочной информации отладка программы в среде Delphi 7 вообще невозможна. Процедура Assert выполняет отладочные функции. В заключительной версии программы она, как правило, не нужна, а удалять ее вызовы из исходного текста неудобно – их могут насчитываться сотни. Отключить генерацию машинного кода для этой процедуры можно с помощью флажка Assertions. Отладочные версии стандартных модулей содержат дополнительные режимы проверки корректности работы с компонентами Delphi 7.

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

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

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

Выполнение по шагам

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

Рассмотрим пример – добавим в обработчик списка действий AddAction следующие описания и операторы:

var Arr: array[1…10] of integer;

begin

for i := 1 to 11 do

if i > 3 then Arr[i] := 0

else Arr[i] := 1;

В данном месте программы скрывается ошибка. Чтобы перейти к выполнению этой подпрограммы по шагам, в ней надо создать точку прерывания или точку остановки, встретив которую программа прервет свою работу и временно передаст управление системе Delphi 7.

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

В нашем случае точку прерывания можно поставить в строке с оператором цикла. Это делается нажатием клавиши F5 или щелчком мыши на синем маркере. При этом соответствующая строка выделяется красным цветом (рисунок 28). Снимается точка прерывания аналогичным способом.

Рисунок 28. Выполнение подпрограммы по шагам

Если теперь запустить программу и выполнить операцию сложения (щелкнув на кнопке Сложить или выбрав соответствующий пункт в строке меню или в контекстном меню), то программа остановится и управление будет передано в систему Delphi 7, где строка с точкой прерывания помечается зеленой стрелкой на левом поле (рисунок 29).

Рисунок 29. Строка с точкой прерывания

В заголовке главного окна системы Delphi 7 появится информационное сообщение Project1 [Stopped] (Выполнение проекта Projectl остановлено).

Далее выполнение метода Add Action Execute можно продолжить по шагам. Для этого используются команда Run v Step Over (Запуск > Перешагнуть), клавиша F8 или кнопка Step Over (Перешагнуть).

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

if i > 3 then Arr[i] := 0

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

Продолжив выполнение метода по шагам, увидим, что следующим выполняемым оператором станет оператор

else Arr[i] := 1;

Предыдущий оператор присваивания Arr[i] := 0 пропущен, потому что условие i > 3 не выполнено. Наконец, на следующем шаге управление опять будет передано оператору цикла, который будет выполнять свое «тело» 11 раз, и на последнем шаге возникнет ошибка.

Полностью остановить работу программы можно с помощью команды Run > Program Reset (Запуск > Сброс программы) или комбинацией клавиш Ctrl+F2. Теперь можно исправить параметр окончания цикла с 11 на 10 и вновь запустить программу. Вернуться к точке прерывания можно, например, щелкнув на кнопке Сложить.

Однако выполнять циклы по шагам не очень удобно. Если число повторений достигает сотен или тысяч, то постоянно жать на клавишу F8 бессмысленно. Чтобы пропустить выполнение группы операторов, можно использовать команду Run > Run to Cursor (Запуск > Выполнение до курсора) или клавишу F4.

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

Label1.Caption := IntToStr(StrToInt(Editl.Text) + StrToInt(Edit2.Text));

Затем следует убрать точку прерывания и нажать клавишу F4. Начнется выполнение цикла и подсветится оператор сложения чисел, введенных в поля. Продолжить выполнение программы можно с помощью команды Run (Запуск) или клавиши F9.

Просмотреть список всех установленных точек прерывания можно с помощью команды View > Debug Windows > Breakpoints (Вид > Окна отладки > Точки прерывания) (рисунок 30).

Рисунок 30. Список установленных точек прерывания

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

procedure TMyForm.Button4Click(Sender: TObject);

begin

AddActionExecute(Sender)

end;

Поставим на вызове этого метода точку прерывания. Запустим программу, щелкнем на новой кнопке, и выполнение прервется в нужном месте. Если теперь нажать на клавишу F8, то подпрограмма AddActionExecute() выполнится за один шаг. Это не всегда удобно – нам хочется выяснить, какова логика работы самого метода AddAction Execute. Для этого надо применить команду Run > Trace into (Запуск > Войти внутрь), нажать клавишу F7 или щелкнуть на кнопке Trace into (Войти внутрь). В результате управление передается первой команде метода AddActionExecute.

Иногда сразу становится ясно, что делает подпрограмма, в которую разработчик вошел с помощью клавиши F7. В таких случаях можно быстро ее покинуть с помощью команды Run > Run Until Return (Запуск > Выполнять до выхода) или комбинации клавиш Shift+F8, в результате чего управление передается на оператор, следующий за вызовом данной подпрограммы. Если программист вошел внутрь метода AddAction Execute, то быстро покинуть его и вернуться в обработчик Button4Click можно с помощью команды Run Until Return (Выполнять до выхода).

Часто в программах встречаются ситуации, когда число вызовов вложенных подпрограмм велико – может достигать десятков. Чтобы взглянуть на подобную последовательность подпрограмм с конкретными параметрами во время выполнения программы, надо выполнить команду View > Debug Windows > Call Stack (Вид > Окна отладки > Стек вызовов).

Просмотр значений

Когда во время работы программы приходится контролировать множество значений разных переменных, использовать для этой цели мышь неэффективно. Система Delphi 7 позволяет помещать переменные в специальное окно, где наряду с их именами показываются также и текущие значения. При выполнении программы по шагам переключаться между этим окном и окном редактора неудобно, поэтому в контекстном меню окна списка переменных имеется пункт Stay on Top (Поверх других окон). Если его включить, это окно будет во время отладки располагаться выше всех остальных окон, что позволяет следить за изменениями переменных при пошаговом выполнении программы. С помощью флажков (крайняя левая колонка) можно включать и выключать отслеживание конкретных переменных.

Добавление новых переменных в такое окно осуществляется с помощью команды Run > Add Watch (Запуск > Добавить слежение) или нажатием клавиш Ctrl+F5. В появившемся окне Watch Properties (Свойства слежения) имя переменной вводится в поле Expression (Выражение) (рисунок 31).

Рисунок 31. Ввод имени переменной в поле Expression

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

В поле Repeat Count (Число элементов) указывается, сколько элементов массива будут отображаться. Например, можно указать элемент массива Аrr[3] и число элементов, равное 5. Тогда при выполнении программы по шагам в этом поле будут отображаться через запятую значения пяти элементов: Arr[3], Arr[4], Arr[5], Arr[6], Arr[7].

В поле Digits (Разрядность) задается число значащих цифр после запятой, которые будут выводиться для чисел дробных типов.

С помощью переключателя Enable (Включено) можно временно отключать контроль значений некоторых переменных списка.

Флажок Allow Function Calls (Разрешить вызов функций) допускает использование в выражениях вызовов функций.

Содержимое переменной, тип которой основан на записи (record), отображается в виде, принятом для инициализации записей:

имя-поля : значение;

Чтобы отредактировать выражение, ранее введенное в список, надо дважды щелкнуть на нем. Удаление выражения производится нажатием клавиши Del. В контекстном меню окна слежения имеются также пункты Delete All Watches (Удалить все элементы), Disable AIL Watches (Отключить все элементы), Enable All Watches (Включить все элементы), позволяющие, соответственно, удалить, временно выключить или включить все элементы. В Delphi 7 имеется возможность объединять элементы в несколько групп, каждой из которых соответствует своя закладка в нижней части окна просмотра. Этот удобный подход позволяет собирать отслеживаемые переменные программы в компактные группы по смыслу, а не показывать в одном длинном списке. Добавление новой группы выполняется командой локального меню просмотра значений Add Group (Добавить группу).

Просмотр и изменение значений

Помимо простого просмотра различных значений во время работы программы иногда требуется какое-нибудь значение изменить. Пусть, например, в процессе отладки по шагам обнаружена ошибка, но выполнение программы желательно продолжить. Чтобы обойти ошибку, неверное значение можно исправить вручную. Это делается в окне быстрого просмотра значений, которое открывается командой Run > Evaluate/Modufy (Запуск > Определить/Изменить) или комбинацией клавиш Ctrl+F7 (рисунок 32).

Рисунок 32. Окно быстрого просмотра значений

В поле Expression (Выражение) вводится вычисляемое выражение. По щелчку на кнопке Evaluate (Вычислить) в поле Result (Результат) появится его значение. Это поле сделано таким большим, потому что в нем отображаются не только отдельные значения, но и массивы и записи. В поле New value (Новое значение) выводится измененное значение. С помощью кнопки Watch (Следить) выражение, указанное в поле Expression (Выражение), можно добавить в окно слежения.

Просмотр и анализ кода

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

Навигатор проекта (Project Browser) вызывается командой View > Browser (Вид > Навигатор) (рисунок 33).

Рисунок 33. Окно Навигатора проекта

Если нажата кнопка Globals (Глобальные объекты), то в левой части окна (Инспектор проекта) отображаются списки используемых в программе классов, типов, свойств, методов, переменных и подпрограмм. Детально настроить способ отображения каждого элемента можно, выбрав в контекстном меню Навигатора пункт Properties (Свойства).

Если нажата кнопка Classes (Классы), отображается детальная иерархическая структура классов, используемых в программе.

Если нажата кнопка Units (Модули), отображаются все модули со взаимными ссылками и входящие в них переменные.

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

Таблица 5. Назначение элементов структуры

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

Если некоторый метод или подпрограмма только определены в интерфейсной части модуля, но не реализованы, их имена выделяются полужирным начертанием. Дважды щелкнув на таком имени, можно перейти к определению соответствующего метода в редакторе, а выбрав в кон-текстном меню (не убирая указатель с имени метода) пункт Complete class at cursor (Закончить реализацию класса), можно автоматически сгенерировать пустую реализацию метода.

Методы быстрой навигации по коду в системе Delphi 7:

  1. Чтобы переключаться между описаниями подпрограммы в интерфейсном разделе и разделе реализации, надо, находясь внутри описания подпрограммы, использовать комбинации клавиш Ctrl+Shift+Up и Ctrl+Shift+Dn.

  2. Чтобы отметить некоторое место в тексте, надо сформировать для него закладку – нажать комбинацию клавиш Ctrl+K и затем цифру от 0 до 9. При этом на внутренней кайме редактора появится зеленый прямоугольник с номером закладки.

В дальнейшем вернуться к нужной закладке можно, нажав комбинацию клавиш Ctrl+номер закладки (например Ctrl+1).

В правой части окна расположен Symbol Explorer (Проводник объектов). Его также можно вызвать командой Search > Browse Symbol (Поиск > Выбор объекта) или непосредственно из редактора, наведя указатель на переменную и выбрав в контекстном меню пункт Browse Symbol at Cursor (Выбрать объект под указателем).

Этот Проводник показывает информацию об объекте, выбранном на левой панели Навигатора проекта. На панели Scope (Область видимости) отображается список идентификаторов, объявленных внутри класса или модуля, на панели In heritance (Наследование) – локальная иерархия в рамках текущего проекта для выбранного класса, на панели References (Ссылки) – список имен файлов и номеров строк в исходном тексте, где описан соответствующий идентификатор. Чтобы перейти к его описанию, надо выполнить двойной щелчок на нужном имени в Проводнике.

Порой разработчик забывает, что означает тот или иной класс или определение. Можно обра-титься к справочной системе или взглянуть на реализацию конкретного определения внутри систе-мы Delphi 7 (в стандартной библиотеке VCL). Для этого служит технология навигации по коду. Находясь в редакторе, надо нажать и удерживать клавишу Ctrl, переместив при этом указатель к нужному определению. Курсор примет вид указательного пальца, а расположенный под ним идентификатор, если он доступен для просмотра, выделяется синим цветом и подчеркиванием.

Теперь достаточно щелкнуть на нем, и редактор переключится на файл, в котором хранится нужное определение. Например, если в модуле Unitl в строке

type

TMyForm = class(TForm)

щелкнуть таким способом на слове TForm, то в редакторе будет открыт файл Forms.pas, а курсор будет установлен в строку с началом определения TForm:

TForm = class(TCustomForm).

В системе Delphi 7 реализовано несколько типов автоподсказок. Они включаются и выключаются в диалоговом окне настроек редактора, которое открывают с помощью пункта Properties (Свойства) в контекстном меню. Для этого используются флажки, расположенные на вкладке Code Insight (Анализ кода), как показано на рисунке 34.

Флажок Code completion (Автозавершение) помогает при вводе членов класса. Когда в редакторе набирается название класса и ставится точка, система отображает список методов этого класса. Подходящий метод можно выбрать с помощью курсорных клавиш без ручного ввода (рисунок 35).

Рисунок 34. Флажки типов автоподсказок

Рисунок 35. Автоматизированный ввод существующих методов

Флажок Code parameters (Параметры вызова) упрощает ввод параметров для метода. Когда введено имя метода и поставлена открывающая скобка, система Delphi 7 подскажет тип следующего параметра (рисунок 36).

Рисунок 36. Сведения о типе очередного параметра

Флажок Tooltip expression evaluation (Быстрое вычисление значений) рекомендуется всегда держать установленным. В этом случае во время отладки значения переменных отображаются во вплывающем окне при наведении указателя.

Флажок Tooltip symbol insight (Информация об описании) управляет отображением всплывающей подсказки, которая поясняет, в каком модуле соответствующий идентификатор описан и какой тип имеет.

С помощью движка Delay (Задержка) устанавливается величина задержки перед появлением всплывающих подсказок (от 0,5 до 1,5 с).