Дальнейшие действия
1.Нажав Ctrl-F2, прерывают выполнение и отладку приложения. Так поступают в случае, когда понятно, где ошибка и как ее исправить. Если же ошибка непонятна, то, прежде чем прервать сеанс работы с приложением, надо получить дополнительную информацию о состоянии переменных, т.е. провести отладку.
2.Можно выполнить команду Запуск|Запустить (или нажать соответствующую быструю кнопку, или клавишу F9), чтобы попытаться, несмотря на ошибку, продолжить вычисления. При этом появится окно с сообщением о виде ошибки (“Floating point overflow”), после закрытия которого можно продолжить работу с приложением. Но это ничего не даст, так как при очередном щелчке на кнопке ситуация с ошибкой повторится.
3.Можно пройти часть программы по шагам (см. далее). Однако предварительно нужно получить соответствующую информацию. Итак, если ошибка неясна, надо получить информацию о происходящих в приложении процессах, приведших к ошибке. Простейший способ – воспользоваться Мастером оценки выражений. Подведем курсор мыши к имени переменной, например A, и увидим текст: “A=1E+308”. Так можно узнать значения переменных программы в данный момент.
Окно наблюдения Список Часов
Это окно позволяет иметь значения нескольких переменных сразу и сравнивать их, что удобно при отладке сложных приложений. Чтобы сделать окно видимым, нужно выполнить команду Вид|Windows отладки|Часы или подвести курсор к требуемой переменной (или выделить ее) и нажать Ctrl-F5. При этом окно наблюдения автоматически откроется и в нем появится имя переменной и ее значение (значение переменной появится только при остановке выполнения приложения и переходе в ИСР C++Builder). Можно выделить выражение, например, Label1->Caption, нажать Ctrl-F5, и в окне появится это выражение. Сообщение “Undefined symbol ‘Label1’” – не определен символ ‘Label1’ объясняется тем, что для окна наблюдения компонент Label1 по умолчанию не считается принадлежащим текущей форме. Добавив Form1-> перед Label1 в обработчике, после нажатия Ctrl-F5 в окне наблюдения увидим выражение и его значение.
Работа с окном наблюдения. Перейдя в него, после щелчка правой кнопкой во всплывшем меню можно выбрать ряд команд. При выборе команд Правка часов и Добавить часы, попадаем в окно Свойства часов. По-другому – в окне наблюдения нажать Ctrl-F5 или сделать двойной щелчок. В окне Выражение можно записать имя любой переменной или любое выражение, содержащее переменные, константы, функции. Окно Повтор счета используется при наблюдении массивов и позволяет задать число наблюдаемых элементов массива. Например, если в окне Выражение указать имя массива, то в окне наблюдений будут отображаться все элементы этого массива. Если же указать первый элемент массива (с индексом 0), а в окне Повтор счета написать 5, то в окне наблюдений будут отображаться только первые 5 элементов массива. Окно Цифр указывает число выводимых значащих разрядов чисел с плавающей запятой. Окно Включить позволяет отключить вывод в окно наблюдения соответствующего выражения во время выполнения приложения, что повышает производительность выполнения. А после того, как приложение остановлено и данное выражение нужно посмотреть в окне наблюдения, выражение выделяют в этом окне и делают на нем двойной щелчок. Откроется окно Свойства часов с загруженным в него выражением и останется только включить индикатор Включить и щелкнуть OK. Индикатор Позволить побочный разрешает или запрещает отображение таких выражений, которые способны вызвать побочные эффекты. Например, в окне Выражение записано ++A. Если индикатор Позволить побочный выключен (он выключен по умолчанию), то в окне наблюдений рядом с выражением ++A появится текст: “Side effects are not allowed.” (побочные эффекты запрещены). Очевидно, если отображать указанное выражение, то значение переменной A в программе изменится. Отображение значения, на единицу большего A, будет иметь место при включении индикатора Позволить побочный. Но следует учесть, что это будет изменять значение переменной A. Радиокнопки в нижней части окна Свойства часов задают формат вывода значения переменной или выражения. По умолчанию формат определяется автоматически по типу отображаемого выражения. Выпадающий список в окне Выражение позволяет выбрать выражение из использовавшихся ранее. В окне Свойства часов имеется выпадающий список − имя группы. По умолчанию создается одна группа − Часы. Закладка этой группы видна в окне Список часов. Но можно разбить наблюдаемые величины на несколько групп (страниц). Для задания новой группы в контекстном меню окна наблюдения надо выбрать раздел Добавить группу и затем указать имя новой группы. Тогда в окне наблюдения появится новая страница, и на нее можно будет заносить новые наблюдаемые величины, выбирая в окне Свойства часов в списке Имя группы соответствующее имя.
Список выражений в окне наблюдения можно редактировать. Для удаления выражения его выделяют и нажимают Delete. Чтобы отредактировать ошибочное выражение, делают на нем двойной щелчок, а затем редактируют в окне Свойства часов.
Вернемся к примеру. В момент появления ошибки выполнения значение A равно , а следующее значение должно быть , которое переменная типа double хранить не может. Теперь можно нажимать Ctrl-F2, прерывать выполнение и исправлять код.
Окно оценки и модификации Оценить|Изменить
Это окно позволяет в процессе отладки не только наблюдать, но и изменять значения переменных. Сделать это окно видимым можно командой Запуск|Оценить|Изменить или командой Отладка|Оценка|Изменение, которую выбирают из контекстного меню, всплывающего при щелчке правой кнопкой в окне Редактора Кода. В окне Выражение можно ввести имя переменной или выражение. Щелкнув на кнопке Оценка, увидим в окне Результат значение этого выражения. Если же в окне Выражение указать имя переменной, а не выражение, то становится доступной кнопка Изменение, позволяющая изменить значение переменной. Следовательно, имеется возможность вмешиваться в процесс выполнения приложения и насильственно изменять значения переменных.
Итак, в окне Выражение укажем имя переменной A, щелкнем на кнопке Оценка и в окне Результат увидим ее значение. В окне Новое значение напишем A/2e300 и щелкнем на кнопке Изменение. В результате значение переменной в приложении изменится, что видно в окне Результат. Перейдя в окно наблюдения (кнопка Часы), там также увидим измененное значение. Поскольку значение Aбылорезко уменьшено, можно продолжить выполнение приложения. Нажимая F9, быстро убедимся, что ошибка переполнения появилась вновь.
Отметим, что возможность оперативно исправить значения переменных, вызванные ошибкой, и продолжить отладку, не запуская выполнение опять сначала, позволяет существенно ускорить отладку при большом времени выполнения приложения.
Пошаговое выполнение приложения
Чаще причина ошибки находится быстрее, если выполнить какой-то фрагмент программы, наблюдая изменения переменных при выполнении каждой команды. Для прохода фрагмента программы по шагам можно использовать следующие команды:
Команда | «Горячие» клавиши | Пояснения |
Через шаг | F8 | Пошаговое выполнение строк программы, считая вызов функции за одну строку, т.е. вход в функции не производится |
След в | F7 | Пошаговое выполнение программы с заходом в вызываемые функции |
Шаг на следующую линию | Shift+F7 | Переход к следующей исполняемой строке |
Выполнить до кур- сора | F4 | Команда выполняет программу до того выполняемого оператора, на котором рас- положен курсор в окне редактора кода |
Выполнить до воз- вращения | Shift+F8 | Выполнение программы до выхода из те- кущей функции, останов на операторе, следующем за вызовом этой функции |
Показать точку выполнения | − | Команда помещает курсор на операторе, который будет выполняться следующим |
Испытаем команды на рассматриваемом примере. Выведем переменную A и выражение Form1->Label1->Caption в окно наблюдения Список часов. Это окно можно встроить в Инспектор Объектов. В режиме проектирования окно наблюдения будет храниться на отдельной странице позади Инспектора Объектов, а во время выполнения приложения страницы Инспектора Объектов будут исчезать, и при остановах можно наблюдать в окне наблюдения значения переменных. Для этого надо сохранить описанную (или любую другую) конфигурацию отладочных окон с помощью команды Вид|Рабочие столы|Сохранить рабочий стол и командой Вид|Рабочие столы|Настройка отладки рабочего стола задать эту конфигурацию как отладочную. Проще осуществлять подобные операции с конфигурациями соответствующими быстрыми кнопками вверху окна ИСР.
Выведя переменную и выражение в окно наблюдения Список часов и встроив это окно в Инспектор Объектов, перейдем в код и откомпилируем модуль. Поместим курсор на строке с оператором A*=10000; Теперь нажмем F4, чтобы приложение выполнялось до строки с курсором. Приложение начнет выполняться. Нажмем в нем кнопку. Перейдем в Редактор Кода. В нем будет выделена строка, на которой стоял курсор перед выполнением. Теперь, нажимая F7 или F8 (в данном случае все равно), выполняем операторы по шагам, а в окне наблюдений следим за изменением переменной и выражения.
Через несколько циклов переведите курсор на оператор, следующий после цикла и задающий значение Label1->Caption. Нажмите F4. Тем самым отладчику указано, что ему надо без остановов выполнять приложение до строки, указанной курсором. Все оставшиеся проходы цикла будут выполнены без остановов, и программа остановится на указанной строке. Если после этого нажать клавишу F7 или F8, то результат будет различным. При нажатии F8 произойдет переход к закрывающей фигурной скобке. А при нажатии F7 сначала попадем в заголовочный файл dstring.h. В этом файле объявлены функции работы со строками типа AnsiString, к которым неявно обращается оператор программы. После нескольких нажатий F7 произойдет возврат в программу.
Точки прерывания
Чтобы ввести простую (безусловную) точку прерывания, достаточно в окне Редактора Кода щелкнуть на полоске левее кода требуемой строки. Строка станет красной, и на ней появится красная точка. (Для удаления точки прерывания достаточно щелкнуть на красной точке.) Если запустить приложение на выполнение, то произойдет прерывание выполнения, как только управление перейдет к строке, в которой указана точка прерывания. Можно одновременно указать несколько точек прерывания в разных местах кода и в разных модулях. Кроме того, в этих точках можно установить условия прерывания.
Точки прерывания можно устанавливать только на выполняемых операторах. Если, например, попробовать установить точку прерывания на строке, содержащей объявление переменной, то в момент запуска приложения в красной точке появится крестик. Это предупреждение о том, что здесь прерывания не будет.
Если задержать курсор над красной точкой, то увидим всплывший ярлык с характеристиками данной точки прерывания. По умолчанию никаких условий останова не задается. Зададим следующие условия: нужно остановиться на введенной точке прерывания, но только на 26-м цикле, причем только при повторном проходе цикла (повторном щелчке пользователя на кнопке приложения).
Щелкните правой кнопкой на красной точке и из всплывшего меню выберите Свойства контрольной точки. Откроется окно Исходные Свойства Контрольной точки.
Два верхних окна редактирования − Имя файла и Номер линии (номер строки файла) в данном режиме недоступны. Они автоматически заполнились в момент, когда была установлена точка прерывания.
В окне Условие укажем условие останова i==26. В окне Счет прохода зададим значение 2.
Окно Группа позволяет задать имя группы, к которой относится данное прерывание. Группировка прерываний позволяет сделать целиком ту или иную группу доступной или недоступной. Это делается с помощью окон Вкл. группу и Выкл. группу, которые становятся доступными после нажатия кнопки Дополнительно. В этих окнах имя группы выбирается из выпадающих списков, содержащих имена введенных ранее групп. В целом, в нижней части окна задания свойств прерывания указываются некоторые действия, выполняемые в момент прерывания. Индикатор Перерыв, установленный по умолчанию, обеспечивает стандартную реакцию − останов выполнения приложения. Индикаторы Игнорировать последующее исключение и Обрабатывать последующее исключение (установлен может быть только один) определяют появление при генерации очередного исключения сообщения отладчика. Если установлен второй индикатор, то сообщение появляется. Если не установлен ни один индикатор, то все определяется настройками отладчика на странице Исключения языка окна настройки отладчика, вызываемого командой Инструменты|Опции отладчика. Пока в перечисленные элементы окна Исходные Свойства Контрольной точки (начиная с окна Группа) никакие изменения вносить не будем.
Список введенных точек прерывания хранится в памяти, и поэтому в любой момент его можно увидеть (и до выполнения программы, и при останове), выполнив команду Вид | Windows отладки | Контрольные точки. Окно Список контрольных точек можно встраивать в окно наблюдения Список часов и фиксировать такую конфигурацию окон как отладочную. Тогда в моменты останова будут видны и наблюдаемые величины, и информация о точках прерывания. В Список часов внесите переменную A и переменную i.
После внесения данных в окно Исходные Свойства Контрольной точки щелкните на OK, откомпилируйте модуль (команда Проект|Компилировать модуль) и запустите выполнение приложения. После первого нажатия кнопки приложения останова не произойдет, а после второго нажатия выполнение остановится. Отметим, что в этот момент A=1E+304, а i=26. Затем, перейдя в Редактор Кода, пройдите по шагам (клавишей F7) последний цикл перед появлением ошибки, наблюдая за окнами Список контрольных точек и Список часов.
В окне Исходные Свойства Контрольной точки в окно Log сообщение запишем сообщение “останов при i=26 во второй раз”, которое будет появляться в момент прерывания в окне Журнал событий, вызываемого командой Вид|Windows отладки|Журнал событий. В окно Eval выражение запишем некоторое выражение (в данном случае просто имя переменной − A), которое будет вычисляться при прерывании. При установленном индикаторе Log результат это выражение и результат его вычисления можно увидеть в том же окне Журнал событий. Выключим индикатор Перерыв и включим индикатор Игнорировать последующее исключение. При этом никаких остановов выполнения приложения в точке прерывания или при генерации исключения не будет происходить. Но после завершения выполнения приложения в Журнале событий окажутся соответствующие сообщения.
Откомпилируем модуль и запустим выполнение приложения. После генерации исключения и выполнения команды Вид|Windows отладки|Журнал событий увидим строки со следующим содержанием:
Breakpoint Message: останов при i=26 во второй раз Process Project1.exe Breakpoint Expression A: 1E+304 Process Project1.exe
Это введенное ранее сообщение (останов при i=26 во второй раз) и выражение (A) с посчитанным результатом.
В нашем примере, где каждый проход запускается нажатием кнопки приложения, очевидно, что ошибка происходит именно при втором проходе цикла. В более сложном варианте определение прохода, на котором происходит ошибка, позволяет сделать условная точка прерывания. Для этого в окне Исходные Свойства Контрольной точки укажем большое значение Счет прохода, например 50. Очевидно, ошибка будет зафиксирована раньше этой точки. Включим индикатор Перерыв и выключим индикатор Игнорировать последующее исключение. Откомпилируем модуль и запустим выполнение приложения. В окне Список контрольных точек будет указано, сколько произошло проходов через точку прерывания с выполнением заданного условия (2 из 50).
В окне Список контрольных точек щелкнем правой кнопкой и во всплывшем меню выберем Добавить. Предлагается три варианта: Исходная контрольная точка − точка прерывания в файле приложения, Адрес точки − прерывание при переходе управления по заданному адресу, и Точка данных − прерывание при изменении данных по заданному адресу. Однако, если работа в окне Список контрольных точек производится не во время выполнения приложения, две последние команды будут недоступны. Это связано с тем, что пока приложение не выполняется, адреса команд и переменных еще не известны.
Выполним пример использования прерывания при изменении данных по заданному адресу. В нашем приложении только один оператор изменяет значение переменной A. В более сложном приложении таких операторов может быть несколько, и поэтому будет неизвестно, какой из них увеличивает значение A настолько, что дальнейшее выполнение приложения приведет к переполнению, или какой оператор заносит в A недопустимое значение. В подобных случаях помогает установка прерывания при изменении данных по заданному адресу − в нашем примере по адресу, отведенному для A. Здесь не устанавливают, на какой строке кода хотят прервать выполнение. Прерывание произойдет на том операторе, который занесет в указанную переменную некоторое значение, если будут выполнены указанные условия.
Воспользуемся оператором, заносящем новое значение в адрес A, причем при значении A> . Поскольку отладчик не знает адреса переменной, пока приложение не загружено в память, то прежде чем задавать точку прерывания, надо запустить приложение на выполнение. Затем, не закрывая приложения и ничего с ним не делая, т.е. не щелкая на кнопке приложения, вводим команду Вид|Windows отладки|Контрольные точки и в открывшемся окне Список контрольных точек щелкнем правой кнопкой мыши. Во всплывшем меню выберем команду Добавить. Из предложенных трех вариантов выберем вариант Точка данных − прерывание при изменении данных по заданному адресу. Откроется окно Добавить контрольную точку данных, подобное окну Исходные Свойства Контрольной точки.
Окно заполняем следующим образом. В окно Адрес заносим переменную A, при изменении которой наступает прерывание. Окно Длина заполняется автоматически. В окна: Условие заносим A>1e299, Счет прохода − 0, Группа − 1, ниже кнопки Дополнительно: Сообщение − значение A>1e299, Eval выражение − A, Вкл. группу − 1, Выкл. группу − 0. Последним действием (занесли 0 в окно Выкл. группу) начинаем отключение прежней точки прерывания. Для завершения отключения выделим ее в окне Список контрольных точек, щелкнем правой кнопкой и выберем Свойства. В открывшемся окне Свойства исходных контрольных точек в окно Группа занесем 0, в окно Вкл. группу − 1, а в окно Выкл. группу − 0. Однако выключить прежнюю точку прерывания можно проще: после щелчка правой кнопкой на строке прежней точки прерывания в окне Список контрольных точек в контекстном меню выбрать Удалить.
Теперь вернемся в выполняющееся приложение и щелкнем кнопкой приложения. Приложение будет выполняться, но значительно медленнее, чем раньше. После второго щелчка приложение остановится на операторе
A*=10000; //Увеличение A в 10000 раз
при состоянии приложения, когда A=1E+300, в чем можно убедиться в окне Список часов и в Журнале событий. Следовательно, прерывание, как и было заказано, произошло после того, как переменная A стала больше 1e299.
Примечание. Доступность точки прерывания по изменению переменной сохраняется только в течение данного сеанса выполнения приложения. По завершению выполнения точка становится недоступной, и при следующем запуске ее надо повторно активизировать. Для этого в контекстном меню, которое появится после щелчка правой кнопкой в окне Список контрольных точек, нужно выбрать Включить группу, а затем − 1.
Добавить точки прерывания можно также командой Запуск|Добавить точку прерывания, первые три первых варианта которой − Контрольная точка источника, Адрес контрольной точки и Данные контрольной точки совпадают с рассмотренными выше.
Имеется также возможность задать точку прерывания по изменению переменной из всплывающего меню окна Список часов (команда Перерыв при замене, доступная только во время выполнения). Это прерывание необходимо, когда надо понять, почему переменная начинает изменяться, а должна быть неизменной. Соответствующая точка возникает в списке точек прерывания, но доступна только в течение данного сеанса выполнения приложения. По завершению выполнения точка становится недоступной и при следующем запуске ее надо повторно активизировать, устанавливая с помощью контекстного меню индикатор Включить.
Использование окна Инспектора Отладки
Инспектор Отладки позволяет получить исчерпывающую информацию о любой переменной в приложении и дает возможность, как и окно Оценить|Изменить, изменить значение переменной и продолжить выполнение приложения с этим новым значением.
Вызов этого инструмента отладки возможен только во время выполнения приложения при останове средствами отладки или вследствие генерации исключения. При останове нужно поставить курсор в окне Редактора Кода и выполнить команду Запуск|Осмотреть. Другой способ − вызвать команду Отладка|Осмотреть из всплывшего контекстного меню после щелчка правой кнопкой в окне Редактора Кода. Проще всего − нажать «горячие» клавиши Alt-F5. Откроется окно Осмотреть, в которое занесем имя переменной A и щелкнем OK. Появится окно Инспектор Отладки, в котором содержатся сведения о переменной A. Нажав кнопку с многоточием, откроем окно Замена, в котором можно изменить значение переменной A, и оно изменится в выполняемой программе. Следовательно, при продолжении выполнения приложения оно будет выполняться с измененным значением переменной.
Инспектор Отладки позволяет исследовать различные данные: переменные, массивы, классы, функции, указатели. В качестве примера в окно Осмотреть занесем Form1−>Label1и, щелкнув OK, перейдем в окно Инспектор Отладки, которое имеет три страницы − Данные, Методы, Свойства. Выбрав страницу Свойства, увидим все свойства компонента, их значения и функции их чтения и записи.
Если нужно изменить какое-то свойство (оно не может быть свойством только для чтения), его выделяют и нажимают появившуюся около него кнопку с многоточием. Появится окно изменения Замена, в котором можно ввести новое значение свойства.
Не все значения свойств могут быть в момент останова досчитаны до конца. В этом случае, если выделить курсором это свойство, около него появляется кнопка со знаком ‘?’. Выделим свойство Caption и увидим, что значение надписи метки не посчитано и не выведено в окне. Если нажать кнопку со знаком ‘?’, то значение будет досчитано и, пока эта кнопка нажата, при каждом останове выполнения свойство будет досчитываться до конца.
Находясь в окне Инспектора Отладки, можно щелкнуть правой кнопкой и выбрать одну из следующих команд:
Диапазон | Просмотр данных в заданном диапазоне |
Замена | Перейти в окно Замена для изменения значения элемен-та |
Показ родственника | Если этот флаг включен, то на страницах окна отобража-ются все свойства и методы, как объявленные в данном классе, так и наследуемые. Если флаг выключен, то ото-бражается только то, что объявлено в данном классе |
Показ полностью составных имен | Отображение наследуемых элементов с их полными именами |
Сортировка по | Два варианта: по порядку объявления и по именам |
Осмотреть | Открывает новое окно для выделения элемента данных. Это позволяет детальнее исследовать данные типа структур, классов, массивов и т.п. |
Убыть | Аналогична команде Осмотреть, но детализирующие данные появляются не в отдельном, а в том же самом окне. В дальнейшем можно вернуться в исходное окно, воспользовавшись расположенным вверху окна выпадающим списком, в котором накапливаются просмотренные объекты |
Новое выражение | Эта команда позволяет задать новое выражение для анализа |
Тип приведения | Позволяет указать другой тип для рассматриваемого объекта, например, указать тип нетипизированного указателя |
Другие средства отладки
В ИСР имеется также инструментарий, позволяющий проводить отладку на более детальном уровне. Окно CPU (команда Вид|Windows отладки|CPU) позволяет отследить ход выполнения проекта на уровне команд макроассемблера. Окно FPU (команда Вид|Windows отладки|FPU) позволяет следить за ходом выполнения операций с плавающей запятой. Окно Стек запроса (команда Вид|Windows отладки|Стек запроса) позволяет определить последовательность вызванных функций, не только тех, которые вызываются явно приложением, но и всех неявно вызываемых функций библиотек. Окно Модули (команда Вид|Windows отладки|Модули) показывает список всех модулей, загруженных в память при выполнении приложения. Это окно позволяет, в частности, если выделить на его левой верхней панели имя модуля .exe, увидеть в левой нижней панели список использованных заголовочных файлов. Двойной щелчок на строке соответствующего файла загрузит его в Редактор Кода, и можно попробовать понять, что именно из данного файла использует приложение.