[Содержание]   [Назад]   [Пред]   [Вверх]   [След]   [Вперед]  


5. Останов программы

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

Внутри DDD, программа может остановиться по нескольким причинам: по сигналу, на точке останова или при достижении следующей строки после команды DDD, такой как `Step'. Тогда вы можете исследовать и изменить значения, установить новые точки останова или удалить старые, а затем продолжить выполнение.

Подчиненные отладчики поддерживают два механизма останова программы при определенных событиях:

5.1 Точки останова

5.1.1 Установка точек останова

Точки останова можно устанавливать по позиции или по имени.

5.1.1.1 Установка точек останова по позиции

Точки останова устанавливаются в определенной позиции программы.

Если исходная строка видима, щелкните слева от нее первой кнопкой мыши, а потом на кнопке `Break'.

Или более быстрый способ: просто нажмите слева от исходной строки третью кнопку мыши и выберите из всплывающего меню пункт `Set Breakpoint'.

PICS/ddd-line-popup

А есть еще более быстрый способ: для установки точки останова просто дважды щелкните слева от исходной строки.

В качестве еще одной альтернативы, вы можете выбрать `Source => Breakpoints'. Щелкните на кнопке `Break' и введите позицию.

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

Точки останова обозначаются простым знаком "стоп" или как `#n', где n -- это номер точки останова. Затененный знак "стоп" (или `_n_') обозначает выключенную точку останова. Знак "стоп" с вопросительным знаком (или `?n?') обозначает условную точку останова или точку останова с установленным счетчиком пропусков.

Если вы установили точку останова по ошибке, удалите ее с помощью `Edit => Undo'.

5.1.1.2 Установка точек останова по имени

Если видимо имя функции, щелкните на нем первой кнопкой мыши. Оно будет скопировано в поле аргумента. Затем щелкните на кнопку `Break', чтобы установить на этой функции точку останова.

Более быстрый способ: просто нажмите на имени функции первую кнопку мыши и выберите из всплывающего меню пункт `Break at'.

Есть еще более быстрый способ: щелкните на `Break...' из редактора точек останова (который вызывается через `Source => Breakpoints') и введите имя функции.

5.1.1.3 Установка точек останова по регулярному выражению

При использовании GDB вы также можете установить точку останова на всех функциях, соответствующих заданной строке. `Break => Set Breakpoints at Regexp ()' устанавливает точку останова на всех функциях, чьи имена соответствуют указанному в `()' регулярному выражению. Вот несколько примеров:

5.1.2 Удаление точек останова

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

Если видимо имя функции, щелкните на нем первой кнопкой мыши. Оно будет скопировано в поле аргумента. Для удаления точки останова щелкните на кнопку `Clear'.

Другой способ, более быстрый: вы можете просто нажать на кнопке останова третью кнопку мыши и выбрать из всплывающего меню пункт `Delete Breakpoint'.

Есть еще более быстрый вариант: можно выделить точку останова и нажать на `Delete' в редакторе точек останова (он вызывается через `Source => Breakpoints').

И самый быстрый способ -- это просто дважды щелкнуть на точке останова, удерживая клавишу Ctrl.

5.1.3 Выключение точек останова

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

Чтобы выключить точку останова, нажмите на ее символе третью кнопку мыши и выберите из появившегося всплывающего меню пункт `Disable Breakpoint'. Чтобы снова включить ее, выберите пункт `Enable Breakpoint'.

PICS/ddd-bp-popup

Другой способ: вы можете выделить точку останова и щелкнуть на `Disable' или `Enable' в редакторе точек останова (который вызывается через `Source => Breakpoints'.

Выключенные точки останова обозначаются серыми знаками "стоп" или как `_n_', где n -- это номер данной точки останова.

Пункт меню `Disable Breakpoint' также доступен по кнопке `Clear'. Чтобы вызвать всплывающее меню, просто нажмите и удерживайте на этой кнопке первую кнопку мыши.

5.1.4 Временные точки останова

Временная точка останова удаляется сразу, как только достигнута.(13)

Чтобы установить временную точку останова, нажмите третью кнопку мыши слева от исходной строки и выберите из всплывающего меню пункт `Set Temporary Breakpoint'.

Есть более быстрый способ: просто дважды щелкните слева от исходной строки, удерживая нажатой клавишу Ctrl.

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

`Continue Until Here' из всплывающего меню устанавливает временную точку останова слева от исходной строки и сразу возобновляет выполнение. Программа останавливается, когда достигнута эта точка.

Пункты `Set Temporary Breakpoint' и `Continue Until Here' также доступны по кнопке `Break'. Чтобы вызвать всплывающее меню, нажмите и удерживайте на этой кнопке первую кнопку мыши.

5.1.5 Редактирование свойств точки останова

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

PICS/ddd-bp-properties

Есть более быстрый способ: можно просто дважды щелкнуть на точке останова.

5.1.6 Условия точки останова

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

Это противоположность операторов контроля; в этом случае вы хотите, чтобы выполнение остановилось, когда контрольное утверждение нарушено --- то есть, когда условие ложно. В Си, если вы хотите проверить утверждение, выражаемое условием утверждение, вы должны установить в соответствующей точке останова условие `!утверждение'.

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

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

5.1.7 Счетчики пропусков точки останова

Особый случай условия точки останова -- останов только тогда, когда эта точка достигалась определенное число раз. Это настолько полезно, что для такого случая есть специальный метод, использующий счетчик пропусков точки останова. У каждой точки останова есть счетчик пропусков; это целое число. Чаще всего оно равно нулю и поэтому эффекта от него нет. Но если ваша программа достигла точки останова с положительным счетчиком пропусков, то вместо останова производится уменьшение счетчика на единицу, а выполнение программы продолжается. В результате, если значение счетчика пропусков равно n, то в этой точке не будет останова еще n раз.

Вы можете задать счетчик пропусков в поле `Ignore Count' из панели свойств точки останова.(15)

Если у точки останова есть положительный счетчик пропусков и условие, то условие не проверяется. Как только счетчик пропусков достигает нуля, DDD начинает проверять условие.

5.1.8 Команды точек останова

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

Вы можете отредактировать эти команды с помощью кнопок `Commands' из панели свойств точки останова.

Чтобы отредактировать команды точки останова, щелкните на `Edit >>' и введите команды в редакторе команд. Завершив редактирование, щелкните на `Edit <<', чтобы закрыть редактор.

При использовании GDB вы можете также записать последовательность команд для выполнения. Чтобы записать последовательность команд, выполните такие три шага:

  1. Щелкните на `Record', чтобы начать запись команд точки останова.
  2. Теперь ведите диалог с DDD. В процессе записи DDD не выполняет команды, а просто записывает их, чтобы выполнить, когда будет достигнута точка останова. Записанные команды показываются в консоли отладчика.
  3. Чтобы завершить запись, щелкните на `End' или введите в подсказке GDB команду `end'. Чтобы отменить запись, щелкните на `Interrupt' или нажмите ESC.
  4. Вы можете отредактировать записанные команды с помощью `Edit >>'.

5.1.9 Перемещение и копирование точек останова

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

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

5.1.10 Поиск точек останова

Если вы хотите найти какую-то точку останова, нажмите `Source => Breakpoints => Lookup'. Когда вы выберете точку останова из списка и щелкните на кнопке `Lookup', будет показана позиция, где находится эта точка.

Или вы можете ввести в поле аргумента `#n', где n --- это номер точки останова, и нажать кнопку `Lookup', чтобы найти ее определение.

5.1.11 Редактирование всех точек останова

Чтобы просмотреть и отредактировать все точки останова одновременно, выберите `Source => Breakpoints'. Появится редактор, который показывает состояние всех точек останова.

PICS/ddd-edit-breakpoints

В редакторе вы можете выбирать отдельные точки останова, щелкая на них. Если при щелчке держать нажатой клавишу Ctrl, выделение переключается. Чтобы отредактировать свойства всех выделенных точек останова, щелкните на `Props'.

5.1.12 Аппаратные точки останова

При использовании GDB через консоль отладчика можно вызывать еще несколько команд, связанных с точками останова:

hbreak позиция
Устанавливает аппаратную точку останова в указанной позиции. Эта команда требует аппаратной поддержки, и некоторые целевые платформы могут ее не поддерживать. Основная цель этой команды -- отладка кода @acronym{EPROM}/@acronym{ROM}, чтобы вы могли установить на некоторой инструкции точку останова, не меняя эту инструкцию.
thbreak позиция
Устанавливает временную аппаратную точку останова в указанной позиции.

См. раздел `Setting Breakpoints' в Debugging with GDB, для дополнительной информации.

5.2 Точки наблюдения

Вы можете сделать так, чтобы программа останавливалась, когда изменяется значение какой-то переменной, или когда значение переменной считывается или записывается. Это называется установкой на переменной точки наблюдения.(18)

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

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

5.2.1 Установка точек наблюдения

Если имя переменной видимо, щелкните на нем первой кнопкой мыши. Имя будет скопировано в поле аргумента. В противном случае, сами введите имя переменной в поле аргумента. Чтобы установить точку наблюдения, нажмите кнопку `Watch'.

При использовании GDB вы можете устанавливать разные типы точек наблюдения. Чтобы получить меню, нажмите и удерживайте первую кнопку мыши на кнопке `Watch'.

5.2.2 Редактирование свойств точек наблюдения

Чтобы изменить свойства точки наблюдения, введите имя наблюдаемой переменной в поле аргумента. Нажмите и удерживайте первую кнопку мыши на кнопке `Watch' и выберите `Watchpoint Properties'.

Панель свойств точки наблюдения предоставляет такую же функциональность, что и панель свойств точки останова (см. раздел 5.1.5 Редактирование свойств точки останова). Есть дополнительная возможность: вы можете щелкнуть на `Print', чтобы увидеть текущее значение наблюдаемой переменной.

5.2.3 Редактирование всех точек наблюдения

Чтобы просмотреть и отредактировать все точки наблюдения сразу, выберите `Data => Watchpoints'. Появится редактор, который показывает состояние всех точек наблюдения.

Редактор точек наблюдения предоставляет такую же функциональность, как редактор точек останова (см. раздел 5.1.11 Редактирование всех точек останова). В качестве дополнительной возможности, вы можете нажать кнопку `Print', чтобы увидеть текущее значение наблюдаемой переменной.

5.2.4 Удаление точек наблюдения

Чтобы удалить точку наблюдения, введите имя наблюдаемой переменной в поле аргумента и нажмите кнопку `Unwatch'.

5.3 Прерывание

Если программа уже запущена (см. раздел 6. Запуск программы), вы можете в любое время прервать ее, нажав кнопку `Interrupt' или набрав в окне DDD ESC.(19) При использовании GDB это эквивалентно посыланию сигнала SIGINT.

`Interrupt' и ESC также прерывают запущенную команду отладчика, такую как печать данных.

5.4 Останов X-программ

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

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

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

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

Есть одна ситуация, когда это не сработает: если вы запрете X-дисплей при работающем DDD, DDD посчитает, что захват указателя случился из-за работы программы, -- и автоматически продолжит выполнение. Поэтому вы можете выключить эту возможность через `Edit => Preferences => General => Continue Automatically when Mouse Pointer is Frozen'.

5.4.1 Настройка проверки захвата

Проверка захвата контролируется следующими ресурсами:

Ресурс: checkGrabs (класс CheckGrabs)
Если это `on' (по умолчанию), DDD проверят после каждого события, не захвачен ли указатель мыши. Если он захвачен, DDD автоматически продолжит выполнение отлаживаемой программы.

Ресурс: checkGrabDelay (класс CheckGrabDelay)
Время ожидания (в миллисекундах) после команды отладчика до проверки захвата указателя. Если DDD заметит в течение этого промежутка времени какое-то событие от мыши, это значит, что указатель не может быть захвачен, и явная проверка не требуется. По умолчанию 5000, или пять секунд.

Ресурс: grabAction (класс grabAction)
Действие, которое нужно выполнить после обнаружения захвата указателя. Это разделяемый переводами строки список команд. По умолчанию это cont, что означает продолжение отлаживаемой программы. Также можно написать kill (уничтожить отлаживаемую программу) или quit (выйти из DDD).

Ресурс: grabActionDelay (класс grabActionDelay)
Время ожидания (в миллисекундах) перед выполнением команд после обнаружения захвата указателя. В течение этого промежутка времени всплывает диалоговое окно, сообщающее пользователю о скором выполнении действий, предпринимаемых при захвате указателя (смотрите ресурс `grabAction' выше). Если указатель отдан в течение этого времени, диалоговое окно исчезает, и действия не производятся. Это делается, чтобы исключить захваты указателя от всех источников, кроме отлаживаемой программы (включая DDD). По умолчанию 10000, или десять секунд.


[Содержание]   [Назад]   [Пред]   [Вверх]   [След]   [Вперед]