Давным-давно, когда
компьютеры были большими, а именно — лет двадцать назад, отладка заключалась
в копании в огромных кипах бумаги с исходными текстами и распечатках результатов
работы и потреблении невероятного количества кофеина, а зачастую и анальгина...
Современный программист, особенно если он программирует на Delphi, больше
не чернорабочий от программирования с крепкими от переворачивания центнеров
бумаги мускулами, а "белый воротничок", окруженный разнообразными ''электронными
мухобойками", предоставляемыми Delphi.
Интегрированный отладчик
Delphi переполнен полезными, не очень полезными и совсем бесполезными возможностями,
и кажется, что изучить их просто невозможно. Однако использование отладчика
Delphi просто, как апельсин: ведь когда
вы компилируете свою программу и запускаете ее из среды Delphi, вы уже
пользуетесь встроенным отладчиком, хотя, вероятно, и не подозреваете об
этом. Как всегда, 90% проблем решается 10% возможностей программного обеспечения,
а потому все разнообразие работы с отладчиком вы можете изучить позднее,
при решении оставшихся 10% ваших проблем.
Настройка
IDE для отладки
Для работы со встроенным
отладчиком Delphi 4 его интегрированная среда разработки (IDE) предлагает
целую серию установок, большинство из которых вам лучше не трогать, а оставить,
как есть (по умолчанию). Однако если вы все-таки решили изменить установки,
выберите команду Tools/Options и в появившемся диалоговом окне Environment
Options щелкните на вкладке Preferences (она показана на рис 2.5)
Ниже перечислены опции
вкладки Preferences и их функции.
Включение
в код отладочной информации
Перед началом отладки
следует убедиться, что в приложение включена отладочная информация Delphi.
Для компиляции проекта
с отладочной информацией следует выполнить команду Project/Options и в
диалоговом окне Project Options выбрать вкладку Compiler (рис. 2.9).
Включение отладочной информации регулируется следующими установками
unit MyUnit;
{$D-}
interface
...
Использование директивы $D- автоматически отключает опции Local Symbols и Symbol Info, так что вам не надо отключать их отдельно.
Пошаговая
отладка
Одна из самых распространенных
задач отладки — выполнение программы шаг за шагом, по одной строке за раз
для проверки правильности выполнения. При пошаговом прохождении кода отладчик
выводит окно редактирования с выполняемой программой. Точка выполнения,
показывающая следующую выполняемую строку программы, представляется в виде
зеленой стрелки, расположенной слева от области исходного текста в окне
редактирования.
После успешной компиляции
модуля на полосе отладочной информации каждая строка кода, внесшая свой
вклад в модуль, будет отмечена маленьким, синим кружком. Если же строка
не помечена, значит, здесь поработал оптимизатор. Поскольку для таких строк
выполняемый код не сгенерирован эти строки не будут помечены точкой выполнения.
Интегрированная среда
Delphi предоставляет пользователю несколько команд пошаговой отладки доступных
в меню Run (рис 2.10)
Ниже перечислены команды отладки.
Просмотр
значений переменных
При пошаговом прохождении
программы в отладчике вы, несомненно, захотите узнать, что содержится в
различных переменных. Для этого можете использовать окно просмотра переменных
Watch List, которое предоставляет возможность пассивно просматривать содержимое
одной или нескольких переменных, или диалоговое окно Evaluate/Modify, позволяющее
работать только с одной переменной (в нем можно не только просмотреть,
но и изменить ее содержимое).
Для просмотра значения
переменной используйте команду Run/AddWatch или установите указатель мыши
на переменную в окне редактирования, щелкните правой кнопкой мыши и выберите
из контекстного меню команду Add Watch at Cursor. После этого появится
диалоговое окно Watch Properties, показанное на рис. 2.12. Введите имя
переменной в поле Expression (если оно не появилось там автоматически).
Обратите внимание на то, что вы можете просматривать значения не только
переменных, но и выражений типа х*(y+z). Единственное ограничение— выражение
не может содержать вызовов функций, поскольку это может вызвать побочный
эффект, связанный с незапланированным вызовом функции, описанный выше,
в подразделе ''Использование директивы Assert". Допускается также просмотр
значений записей, массивов и других структурированных элементов.
Поле Repeat Count используется
в том случае, если у вас есть большой массив, и вы хотите просмотреть его
часть. Предположим, что вам надо знать значения элементов 826-833 следующего
массива
var
BigArray: array[1..1000] of Integer;
Вы не можете просмотреть
массив BigArray, так как 1 000 элементов просто не поместятся в окне (да
и пролистать ненужные вам 825 элементов — работенка немалая!) Вместо этого
вы просите показать вам значение BigArray [826] и устанавливаете параметр
Repeat Count равным 8. При этом вам будут показаны значения восьми элементов
массива— от 826 по 833.
Использование поля
Digits позволяет определить количество значащих цифр при выводе числа с
плавающей точкой.
Отключенная опция Enabled
предотвращает вывод значения переменной, однако,
среда будет хранить все параметры, заданные для ее просмотра. Так, вы можете
временно убрать с экрана информацию о переменной, которая в настоящий момент
вам не нужна, и быстро восстановить ее на экране при необходимости без
повторного ввода характеристик просмотра.
В диалоговом окне имеется
также набор переключателей для выбора способа представления переменной.
Значение Default позволяет среде разобраться с типом переменной самостоятельно.
Как правило, такое решение оптимально, однако в любой момент вы можете
представить переменную как переменную того типа, который вас интересует.
Опция Memory dump представляет информацию как набор байтов, что бывает
полезно, когда необходимо увидеть внутреннее представление информации в
переменной.
На рис 2.13 отображены значения нескольких
переменных в окне Watch List. Кроме того, в некоторых случаях отладчик
выводит информацию о причинах, по которым содержимое переменной недоступно.
Смысл приведенных сообщений поясняется ниже
Диалоговое
окно Evaluate/Modify
Для вывода диалогового
окна Evaluate/Modify выберите команду Run/Evaluate/Modify (рис 2.14). Другой
способ вызова диалогового окна — установить курсор в окне редактирования
на необходимой вам переменной, щелкнуть правой кнопкой мыши и в контекстном
меню выбрать команду Evaluate/Modify.
Введите выражение в
поле Expression так же, как в диалоговом окне Watch Properties (см рис
2.12). Затем щелкните на кнопке Evaluate для того, чтобы увидеть результат
в поле Result. Если выражение состоит только из имени простой переменной
(не массива или структуры!), можете ввести новое значение для переменной
в поле New Value и, щелкнув на кнопке Modify, присвоить переменной новое
значение. Это позволяет корректировать значения переменных в процессе отладки,
не останавливаясь и не перекомпилируя всю программу, что сбережет ваше
время и нервы, и даст возможность, найдя одну ошибку, искать другие, а
исправлением первой ошибки заняться чуть позже.
Диалоговое окно Evaluate/Modify — немодальное, т.
е. вы можете не закрывать его, продолжая отладку. Однако учтите, что в
отличие от окна Watch List диалоговое окно Evaluate/Modify не отслеживает
изменения значений переменных и для получения информации о текущем состоянии
переменной вам необходимо воспользоваться кнопкой Evaluate.
Так же, как и окно
Watch List, диалоговое окно Evaluate/Modify может выводить сообщения об
ошибках, если отладчик не в состоянии вывести информацию о переменных.
И точно так же не выводится информация о выражениях, содержащих вызов функций.
Как видите, окно Watch
List и диалоговое окно Evaluate/Modify очень похожи, но каждое из них имеет
свои преимущества в различных ситуациях. Обратите внимание на одно существенное
отличие диалогового окна Evaluate/Modify его вывод выполняется в поле с
несколькими строками, а потому оно более удобно для просмотра структур
и объектов.
Установка
точек останова
Точка останова (breakpoint)
— своеобразный знак STOP для отладчика (на полосе слева в окне редактора
она и выглядит как маленький красный значок). Когда ваше приложение запущено
под отладчиком и доходит до строки, в которой находится точка останова,
оно прекращает работу и ждет ваших дальнейших распоряжений. Такие точки
могут быть условными и безусловными. Отладчик всегда останавливается на
точке безусловного останова и может останавливаться в точке условного останова,
когда выполнено условие. Интегрированный отладчик Delphi поддерживает два
типа условий — логическое и по количеству проходов. Ниже рассмотрены оба
типа.
Установить точки останова
можно следующими способами:
После щелчка
правой кнопкой мыши в окне при невыбранной точке останова выводится контекстное
меню, в котором команда Add служит для добавления новой точки, Delete All
удаляет все точки останова, а команды Disable All и Enable All отключают
или включают все точки останова в списке.
Для превращения безусловной
точки останова в условную, необходимо вызвать диалоговое окно Edit breakpoint
(см. рис. 2.15) и ввести условное выражение или количество проходов в соответствующие
поля.
Условное выражение,
введенное в поле Condition, может быть любым логическим выражением. По
достижении точки останова отладчик вычисляет значение выражения и, если
результат ложен, продолжает выполнение программы. Если выражение истинно,
выполнение программы приостанавливается. Как обычно, выражение не должно
использовать вызов функции. Такие точки останова полезны, если вы можете
попасть в интересующий вас фрагмент кода различными путями, но вы хотите
остановить выполнение программы только при достижении каких-либо конкретных
условий.
Ненулевое значение,
введенное в поле Pass count, дает отладчику задание продолжать выполнение
программы при прохождении через точку останова, пока через нее не будет
выполнено соответствующее количество проходов. При каждом проходе через
точку останова отладчик уменьшает значение счетчика на единицу и по достижении
нулевого значения программа приостанавливается. Такой метод полезен при
работе с циклами, особенно если вы знаете, что ошибка происходит после
определенного количества циклов.
Сейчас, когда вы изучили
основы технологии отладки, вероятно, у вас возникло желание поставить точку
останова у себя в голове и поработать с точками останова в программах.
Кстати, один из отличных методов понять, как работает та или иная
программа, — проследить за ее пошаговым выполнением, а поскольку ни установка
точек останова, ни просмотр или изменение переменных не изменяют текста
программы, вы можете работать смело, не опасаясь каким-либо образом "поломать"
используемое в учебных целях приложение.
Отладка
DLL
В предыдущих версиях
Delphi для отладки библиотек динамической компоновки требовался внешний
отладчик (Turbo Debugger for Windows). Delphi 4 внесла возможность отладки
DLL в список своих возможностей. Windows не может загрузить DLL без предварительной
загрузки использующего ее ЕХЕ, поэтому вам с начало придется набросать
простенькую программку, использующую интересующую вас DLL. В главном меню
выберите команду Run/Parameters для вывода диалогового окна Run Parameters.
Если текущий проект— DLL (DPR-файл начинается ключевым словом library,
а не program), поле Host Application будет доступно, и в нем вам надо либо
ввести имя использующей DLL программы, либо выбрать его с помощью кнопки
Browse.
После выбора приложения
запуск и отладка DLL становятся обычной рутинной работой со всеми возможностями,
используемыми при отладке программ, — установкой точек останова, просмотром
значений переменных и т.д.
Точно так же вы будете
отлаживать и свои компоненты ActiveX, и объекты автоматизации OLE.
Окно
CPU (дизассемблер)
Окно CPU предоставляет
возможность увидеть работу приложения на уровне языка ассемблера.
Те, кто использовали отладчик Turbo Debugger for Windows, должны знать
возможности, предоставляемые таким окном. Эффективное его использование
предполагает знание ассемблера Intel x86 и архитектуры процессора, так
что, если вы не вполне уверенно себя чувствуете, можете пропустить этот
раздел.
Окно CPU требуется
крайне редко, но если в нем возникла необходимость, значит,
это действительно необходимость. Это — ultima ratio, последний довод, и
используется он в безвыходных положениях, когда обычная трассировка кода
не позволяет найти, понять и исправить ошибки. Только в таких случаях окно
CPU и проход по ассемблерным инструкциям может приподнять завесу над причиной
возникновения ошибок.
Чтобы использовать окно CPU необходимо
его включить (по умолчанию оно отключено). Для этого придется использовать
программу RegEdit из поставки Windows 95 (Windows NT). Запустите RegEdit
и пробирайтесь по иерархическому дереву папок. Сначала откройте папку HKEY_CURRENT_USER.
Во вложенной ветви зайдите в папку Software, затем — в Borland, Delphi
и, наконец, в 4.
Одна из папок называется
Debugging. Щелкните на ней и, когда она откроется, появится список пар
Имя/Данные в окошке справа. Добавьте новое значение с именем EnableCPU
и значением 1.
При следующем запуске
Delphi вы увидите новый подпункт меню View/CPU Window.
Для вывода окна выберите
View/CPU Window.
Перечислим панели
Окно
состояния подзадач.
Окна Thread Status,
Modules и Call Stack предоставляют дополнительную информацию, которая может
быть полезна при отладке приложения.
В окне Thread Status
перечислены все активные подзадачи текущего процесса. Для просмотра состояния
подзадач выберите команду View/Threads, и на экране появится окно Thread
Status (рис 2.17).
В четырех колонках окна представлена следующая информация:
Окно
Modules
В окне Modules отображаются
все модели (ЕХЕ-файл вашего приложения и все используемые динамические
библиотеки), которые располагаются в адресном пространстве приложения.
В него входят непосредственно подключенные DLL и библиотеки, подключенные
через другие библиотеки, а также библиотеки, загруженные операционной системой.
Чтобы увидеть это окно, изображенное на рис 2.18. выберите команду View/Modules.
В окне информация выводится в трех столбцах Name (имя модуля), Address
(адрес начала кода модуля) и Path (полный
путь каталога, из которого был загружен модуль). Информация о каталоге
может быть важна, если возможна загрузка модуля не из того каталога, из
которого ожидалась, например, в более старой версии. Информация об адресе
обычно используется при отладке в окне CPU.
Окно
Call Stack
В этом окне представлен
список всех функций и процедур, вызванных к моменту достижения точки выполнения
и работа которых приостановлена. Для открытия этого окна, показанного на
рис 2.19, используйте команду View/Call Stack.
В верхней строке окна выводится имя текущей процедуры (DontHitMe в приведенном примере). В следующей строке указывается имя процедуры, вызвавшей данную процедуру (Ouch) и т.д. Это окно может быть очень полезным, когда надо определить, каким путем вы достигли точки останова. Дополнительные возможности предоставляет контекстное меню окна, которое можно вызвать, щелкнув правой кнопкой мыши.
Трассировка
исходного кода VCL
Если вы используете
соответствующую версию поставки Delphi 4, значит, в нее входят исходные
тексты VCL (Visi Component Library). В поставку VCL входят скомпилированными
без отладочной информации, что означает, что при отладке вы не сможете
пройти код пошагово. Нет особой необходимости трассировать код VCL, но
если вы хотите убедиться, что ошибка не в VCL, или посмотреть, как работает
функция, придется перекомпилировать модули, которые нужно трассировать,
с отладочной информацией.