This document was generated on December, 29 2000 using texi2html
This document was generated on December, 29 2000 using texi2html
Назначение отладчика, такого как DDD, -- позволить вам увидеть, что происходит "внутри" другой программы в процессе ее работы, -- или узнать, что делала другая программа в момент краха.
DDD может выполнять четыре основные операции (плюс другие вещи для поддержки этих четырех), чтобы помочь вам поймать ошибки в действии:
Говоря технически, DDD является интерфейсом к отладчику, управляемому из командной строки (он называется подчиненным отладчиком, поскольку работает на уровень ниже DDD). DDD поддерживает следующие подчиненные отладчики:
См. раздел 2.1.1 Выбор подчиненного отладчика, чтобы выбрать подходящий подчиненный отладчик. См. раздел 1. Пример сеанса DDD, чтобы получить первое впечатление о DDD.
Данное руководство поставляется в нескольких форматах:
info
или из DDD через `Help => DDD Manual'.
Дистрибутив исходных текстов DDD,
`ddd-3.2.1.tar.gz', включает это руководство в
виде уже отформатированных Info-файлов; вы также можете взять их на
WWW-странице DDD.
Само руководство написано в формате Texinfo; его исходный файл `ddd.texi' находится в дистрибутиве исходников DDD `ddd-3.2.1.tar.gz'.
Рисунки поставляются в отдельном пакете `ddd-3.2.1-pics.tar.gz'; он понадобится вам, только если вы захотите сами создать PostScript-, HTML- или PDF-версии.
DDD распространяется свободно; это означает, что каждый волен его использовать и повторно распространять на свободной основе. DDD не является общественным достоянием; он защищен законами об авторских правах, и на его распространение накладываются некоторые ограничения, но ограничения эти написаны так, чтобы позволить все, что может захотеть хороший благонамеренный гражданин. Что не разрешается, так это пытаться мешать другим и далее совместно пользоваться любой версией этих программ, которые они могли бы от вас получить. Точные условия находятся в Универсальной Общественной Лицензии GNU, которая поставляется вместе с DDD; См. раздел G. Универсальная Общественная Лицензия GNU, для получения подробностей.
Простейший способ получить копию DDD -- взять ее у кого-нибудь, у кого он уже есть. Вам не нужно спрашивать на это разрешения или говорить об этом кому-то; просто скопируйте.
Если у вас есть доступ к Интернету, вы можете получить последнюю версию DDD с анонимного FTP-сервера `ftp.gnu.org' в каталоге `/gnu/ddd'. В нем должны лежать следующие файлы:
DDD также можно найти на многих других архивных сайтах по всему миру; последний список известных сайтов смотрите в файле `ANNOUNCE' в дистрибутиве DDD.
Изначально авторами DDD были Доротеа Люткехаус и Андреас Зеллер. В его разрабутку внесли вклад и многие другие. Практически все они упомянуты в файлах `ChangeLog' и `THANKS' из дистрибутива DDD.
История DDD -- это история переработки кода. Самые старые части были написаны в 1990-ом году, когда Андреас Зеллер придумал VSL, визуальный язык структур для отображения структур данных и программ. Интерпретатор VSL и библиотека Box стали частью дипломной работы Андреаса: графического синтаксического редактора, основанного на Генераторе Программных Систем @acronym{PSG}.
В 1992-ом году библиотеки VSL и Box были использованы для проекта @acronym{NORA}. Для этого проекта, экспериментального инструмента для разработки программ, основанного на логическом выводе, Андреас написал редактор графов (базируясь на библиотеках VSL и Box) и средства для обмена знаниями между процессами. Используя эти инструменты, Доротеа Люткехаус (теперь Доротеа Крабилл) реализовала в 1994-ом году DDD как свою дипломную работу.
В первом DDD не было окна с исходным текстом; Доротеа добавила это зимой 1994--1995. В первом квартале 1995-ого Андреас наконец закончил DDD, добавив окна команд и выполнения, расширения для DBX и удаленной отладки, а также поддержку конфигурирования для нескольких архитектур. С тех пор Андреас сопровождал и расширял DDD, опираясь на комментарии и предложения от нескольких пользователей DDD со всего мира. Подробности смотрите в комментариях к исходному коду DDD.
Основные связанные с DDD события:
Вы можете читать это руководство на досуге, чтобы узнать все о DDD. Однако, чтобы приступить к использованию отладчика, достаточно знать лишь несколько возможностей. Они описаны в данной главе.
Программа-пример `sample.c' (см. раздел 1.1 Пример программы) обнаруживает
следующую ошибку. Программа sample
должна сортировать и
печатать свои аргументы в виде чисел, как в этом примере:
$ ./sample 8 7 5 4 1 3 1 3 4 5 7 8
Однако, при некоторых значениях аргументов она ошибается:
$ ./sample 8000 7000 5000 1000 4000 1000 1913 4000 5000 7000
Хотя вывод отсортирован и содержит верное число аргументов, некоторые
аргументы пропущены и заменены на странные числа; в данном случае
пропущено 8000
, а вместо него стоит 1913
.(3)
Давайте применим DDD, чтобы увидеть, что происходит. Сначала вы
должны скомпилировать `sample.c' для отладки (см. раздел 4.1 Компиляция для отладки), задав при компиляции флаг -g
:
$ gcc -g -o sample sample.c
Теперь вы можете вызвать DDD (см. раздел 2.1 Вызов DDD) для исполняемого файла
sample
:
$ ddd sample
Через несколько секунд появляется DDD. Окно с исходным текстом содержит код отлаживаемой программы; для прокрутки по файлу используйте полоску прокрутки.
Консоль отладчика (в самом низу) содержит информацию о версии DDD, а также подсказку GDB.(4)
GNU DDD Version 3.2.1, by Dorothea L@"utkehaus and Andreas Zeller. Copyright (C) 1999 Technische Universit@"at Braunschweig, Germany. Copyright (C) 1999 Universit@"at Passau, Germany. Reading symbols from sample...done. (gdb)
Первое, что нужно сейчас сделать -- установить точку останова
(см. раздел 5.1 Точки останова), что заставит sample
остановиться в
интересующем вас месте. Щелкните на пустом месте слева от инициализации
a
. Поле аргумента `():' теперь содержит позицию
(`sample.c:31'). Теперь щелкните на `Break', чтобы создать
точку останова в позиции `()'. Вы увидите, что на строке 31
появился маленький знак "стоп".
Следующее, что нужно сделать, -- действительно запустить программу, чтобы вы могли исследовать ее поведение (см. раздел 6. Запуск программы). Для запуска программы выберите `Program => Run'; появится диалоговое окно `Run Program'.
Теперь вы можете ввести в поле `Run with Arguments' аргументы
программы sample
. Введите здесь аргументы, приводящие к
ошибочному поведению -- то есть, `8000 7000 5000 1000 4000'.
Щелкните на `Run', чтобы началось выполнение с заданными вами
аргументами.
Теперь GDB запускает sample
. Через несколько мгновений,
когда достигнута точка останова, выполнение останавливается. Об этом
сообщается в консоли отладчика.
(gdb) break sample.c:31 Breakpoint 1 at 0x8048666: file sample.c, line 31. (gdb) run 8000 7000 5000 1000 4000 Starting program: sample 8000 7000 5000 1000 4000 Breakpoint 1, main (argc=6, argv=0xbffff918) at sample.c:31 (gdb)
Выполняемая в текущий момент строка обозначена зеленой стрелкой.
=> a = (int *)malloc((argc - 1) * sizeof(int));
Сейчас вы можете проверить значения переменных. Чтобы проверить простую
переменную, вы можете просто поместить указатель мыши над ее именем и
задержать его там. Спустя секунду всплывет маленькое окно со значением
этой переменной (см. раздел 7.1 Просмотр простых значений с помощью подсказок). Попробуйте проделать
это с `argv', чтобы увидеть ее значение (6
). Локальная
переменная `a' пока не проинициализирована; вы, вероятно, увидите
0x0
или какое-то другое значение неверного указателя.
Чтобы выполнить текущую строку, щелкните на кнопке `Next' из командной панели. Стрелка продвинется на следующую строку. Теперь снова укажите на `a' и увидите, что значение изменилось, и переменная `a' действительно стала инициализированной.
Чтобы исследовать отдельные значения массива `a', введите в поле аргумента `a[0]' (вы можете заранее очистить его, щелкнув на `():'), а затем щелкните на кнопку `Print'. Это напечатает текущее значение `()' в консоли отладчика (см. раздел 7.2 Печать простых значений в консоли отладчика). В нашем случае вы получите
(gdb) print a[0] $1 = 0 (gdb)
или какое-то другое значение (заметьте, что `a' была только размещена, но ее содержимое еще не проинициализировано.)
Чтобы увидеть все члены `a' одновременно, вы должны применить
особый оператор GDB. Поскольку `a' была размещена динамически,
GDB не знает ее размера; вы должны явно указать его, используя
оператор `@' (см. раздел 7.3.2.1 Фрагменты массива). Введите в поле
аргумента `a[0]@(argc - 1)' и щелкните кнопку `Print'. Вы
получите первые argc - 1
элементов `a', или
(gdb) print a[0]@(argc - 1) $2 = {0, 0, 0, 0, 0} (gdb)
Вместо того чтобы использовать `Print' для просмотра текущего значения `a' на каждом останове, вы можете также отобразить `a', то есть сделать так, чтобы ее значение показывалось автоматически. Щелкните на `Display' оставив в поле аргумента `a[0]@(argc - 1)'. Содержимое `a' теперь показывается в другом окне, окне данных. Для горизонтального поворота массива щелкните на `Rotate'.
Далее идет присваивание значений членам `a':
=> for (i = 0; i < argc - 1; i++) a[i] = atoi(argv[i + 1]);
Теперь вы можете щелкать на `Next' и снова на `Next', чтобы увидеть, как происходит присваивание отдельным членам `a'. Измененные члены подсвечиваются.
Для продолжения выполнения цикла используйте кнопку `Until'. Она велит GDB выполнять программу до тех пор, пока не будет достигнута строка, большая текущей. Щелкайте на `Until', пока не окажетесь на вызове `shell_sort':
=> shell_sort(a, argc);
В этом месте содержимое `a' должно быть равно `8000 7000 5000 1000 4000'. Снова щелкните на `Next', чтобы пройти через вызов `shell_sort'. DDD остановится на цикле
=> for (i = 0; i < argc - 1; i++) printf("%d ", a[i]);
и вы увидите, что после окончания `shell_sort' содержимое `a' стало равным `1000, 1913, 4000, 5000, 7000' -- то есть `shell_sort' каким-то образом испортил его.
Чтобы выяснить, что же случилось, выполните программу снова. На этот раз не проходите инициализацию, а перескочите прямо на вызов `shell_sort'. Удалите старую точку останова, выбрав ее и щелкнув на `Clear'. Затем создайте новую точку останова в строке 35, перед вызовом `shell_sort'. Для повторного выполнения программы выберите `Program => Run Again'.
Опять же, DDD остановится перед вызовом `shell_sort':
=> shell_sort(a, argc);
На этот раз вы хотите ближе исследовать, что делает `shell_sort'. Щелкните на `Step', чтобы войти в вызов `shell_sort'. Это оставит вашу программу на первой исполняемой строке,
=> int h = 1;
тогда как консоль отладчика говорит нам, что произошел вход в функцию:
(gdb) step shell_sort (a=0x8049878, size=6) at sample.c:9 (gdb)
Такой вывод, показывающий функцию (и ее аргументы), где остановлено выполнение `sample', называется отображением стека фреймов. Он дает представление о содержимом стека. Вы можете использовать `Status => Backtrace', чтобы узнать, в каком месте стека вы находитесь; если выбрать строку (или щелкнуть на `Up' или `Down'), вы сможете перемещаться по стеку. Обратите внимание на то, что отображение `a' исчезает, когда вы покидаете его фрейм.
Давайте теперь проверим правильность аргументов `shell_sort'. Вернувшись в самый нижний фрейм, введите в поле аргумента `a[0]@size' и щелкните на `Print':
(gdb) print a[0] @ size $4 = {8000, 7000, 5000, 1000, 4000, 1913} (gdb)
Сюрприз! Откуда взялось это лишнее значение 1913
? Ответ прост:
размер массива, передаваемый в функцию `shell_sort' как
`size', больше чем нужно на единицу -- странное число
1913
оказалось в памяти после `a'. И это значение также
сортируется.
Чтобы понять, действительно ли это является причиной ошибки, вы можете теперь присвоить `size' правильное значение (см. раздел 7.3.3 Присваивание переменных). Выберите в исходном коде `size' и щелкните на `Set'. Появится диалоговое окно, где вы можете отредактировать значение этой переменной.
Измените значение `size' на 5
и щелкните на `OK'.
Затем щелкните на `Finish', чтобы продолжить выполнение функции
`shell_sort':
(gdb) set variable size = 5 (gdb) finish Run till exit from #0 shell_sort (a=0x8049878, size=5) at sample.c:9 0x80486ed in main (argc=6, argv=0xbffff918) at sample.c:35 (gdb)
Получилось! Для `a' теперь показаны корректные значения `1000, 4000, 5000, 7000, 8000'.
Вы можете убедиться, что эти значения будут на самом деле напечатаны на стандартный вывод, выполнив программу дальше. Щелкните на `Cont', чтобы продолжить выполнение.
(gdb) cont 1000 4000 5000 7000 8000 Program exited normally. (gdb)
Сообщение `Program exited normally.' исходит от GDB; оно
говорит, что программа sample
завершила выполнение.
Найдя причину ошибки, вы теперь можете исправить исходный код. Щелкните на `Edit', чтобы отредактировать `sample.c', и измените строку
shell_sort(a, argc);
на корректный вызов
shell_sort(a, argc - 1);
Теперь вы можете перекомпилировать sample
$ gcc -g -o sample sample.c
и проверить (через `Program => Run Again'), что
sample
работает хорошо.
(gdb) run `sample' has changed; re-reading symbols. Reading in symbols...done. Starting program: sample 8000 7000 5000 1000 4000 1000 4000 5000 7000 8000 Program exited normally. (gdb)
Все готово; сейчас программа работает правильно. Вы можете завершить этот сеанс DDD с помощью `Program => Exit' или Ctrl+Q.
Это исходный файл `sample.c' программы-примера.
/* sample.c -- Sample C program to be debugged with DDD */ #include <stdio.h> #include <stdlib.h> static void shell_sort(int a[], int size) { int i, j; int h = 1; do { h = h * 3 + 1; } while (h <= size); do { h /= 3; for (i = h; i < size; i++) { int v = a[i]; for (j = i; j >= h && a[j - h] > v; j -= h) a[j] = a[j - h]; if (i != j) a[j] = v; } } while (h != 1); } int main(int argc, char *argv[]) { int *a; int i; a = (int *)malloc((argc - 1) * sizeof(int)); for (i = 0; i < argc - 1; i++) a[i] = atoi(argv[i + 1]); shell_sort(a, argc); for (i = 0; i < argc - 1; i++) printf("%d ", a[i]); printf("\n"); free(a); return 0; }
В этой главе обсуждается, как запустить DDD и как выйти из него. В двух словах:
Обычно вы можете запустить DDD, вызвав программу
ddd
.
Вы также можете запустить DDD с различными аргументами и ключами, чтобы с самого начала конкретнее определить среду отладки.
Чаще всего DDD запускают с одним аргументом, указывающим исполняемую программу:
ddd программа
Если вы используете в качестве подчиненного отладчика GDB, DBX, Ladebug или XDB, вы также можете указать при запуске исполняемую программу и файл с дампом памяти:
ddd программа дамп
Если вы собираетесь отлаживать работающий процесс, вы можете вместо этого задать в качестве второго аргумента ID этого процесса, например,
ddd программа 1234
присоединит DDD к процессу 1234
(если нет файла с именем
`1234'; DDD сначала ищет файл с дампом памяти).
Вы можете управлять и другими аспектами DDD, вызывая его с определенными ключами. Чтобы получить список ключей DDD, вызовите его как
ddd --help
Наиболее важны ключи для указания подчиненного отладчика (см. раздел 2.1.1 Выбор подчиненного отладчика), но вы можете также настроить при запуске несколько аспектов DDD (см. раздел 2.1.2 Ключи DDD).
Кроме того, DDD понимает обычные ключи X, такие как -display
или -geometry
. См. раздел 2.1.3 Ключи X Windows, для получения подробностей.
Все аргументы и ключи, не распознанные DDD, передаются подчиненному
отладчику; раздел 2.1.4 Ключи подчиненного отладчика. Чтобы передать
подчиненному отладчику ключ, который конфликтует с ключом X или
перечисленным здесь ключом DDD, используйте ключ --debugger
(см. раздел 2.1.2 Ключи DDD).
Чаще всего требуются ключи для выбора конкретного подчиненного отладчика. Обычно выбор подчиненного отладчика определяется тем, какую программу нужно анализировать:
ddd --jdb программа
ddd --pydb программа
ddd --perl программадля запуска DDD с JDB, PYDB или Perl в качестве подчиненного отладчика.
ddd --gdb программа
ddd --dbx программа
ddd --ladebug программа
ddd --xdb программадля запуска DDD с GDB, DBX, Ladebug или XDB в качестве подчиненного отладчика.
Если вы вызываете DDD без этих ключей, но указываете анализируемую программу, то DDD выберет подчиненный отладчик автоматически:
См. раздел 2.5 Настройка диалога с подчиненным отладчиком, для получения подробностей об определении подчиненного отладчика.
Вы можете детальнее управлять запуском DDD, используя перечисленные
ниже ключи. Все ключи можно сокращать, если это не приводит к
неоднозначности; вместо двойного дефиса --
можно использовать
одинарный -
. Практически каждый ключ контролирует особый
ресурс или класс ресурсов DDD (см. раздел 3.6 Настройка DDD).
--attach-windows
--attach-source-window
--attach-data-window
--automatic-debugger
--button-tips
--configuration
--check-configuration
--data-window
--dbx
--debugger имя
gdb
,
dbx
, xdb
, jdb
, pydb
или
perl
).
Этот ключ также можно использовать для передачи подчиненному отладчику
ключей, которые иначе конфликтовали бы с ключами DDD. К примеру,
чтобы передать XDB ключ -d каталог
, напишите так:
ddd --debugger "xdb -d каталог"Если вы применяете ключ
--debugger
, убедитесь, что указан также
и тип подчиненного отладчика. То есть используйте один из ключей
--gdb
, --dbx
, --xdb
, --jdb
,
--pydb
или --perl
(если только принимаемые по
умолчанию установки не срабатывают).
Указание этого ключа эквивалентно установке ресурса DDD
`debuggerCommand' в значение имя. См. раздел 2.5 Настройка диалога с подчиненным отладчиком, для дополнительной информации.
--debugger-console
--disassemble
--no-disassemble
ниже.
Указание этого ключа эквивалентно установке ресурса DDD
`disassemble' в значение `on'. См. раздел 4.4 Настройка окна исходного кода,
для получения подробностей.
--exec-window
--font имя-шрифта
-fn имя-шрифта
--fonts
--fontsize размер
--fontsize
120
.
Указание этого ключа эквивалентно установке класса ресурсов DDD
`FontSize' в значение `размер'. См. раздел 3.6.4.3 Настройка шрифтов, для
дополнительной информации.
--fullname
-f
-fullname
,
который подходит для программ-интерфейсов отладчика. По умолчанию
выключаются консоль отладчика и окно исходного кода. См. раздел 10.2 Ввод команд с терминала,
обсуждение TTY-интерфейса.
Указание этого ключа эквивалентно установке класса ресурсов DDD
`TTYMode' в значение `on'. См. раздел 10.2 Ввод команд с терминала, для
дополнительной информации.
--gdb
--glyphs
--no-glyphs
ниже.
Указание этого ключа эквивалентно установке ресурса DDD
`displayGlyphs' в значение `on'. См. раздел 4.4 Настройка окна исходного кода,
для получения подробностей.
--help
-h
-?
--host имя-машины
--host имя-пользователя@имя-машины
--login
, использовать имя-пользователя как имя
удаленного пользователя. См. раздел 2.4.2 Использование DDD с удаленным подчиненным отладчиком, для получения
подробностей.
Указание этого ключа эквивалентно установке ресурса DDD
`debuggerHost' в значение имя-машины. См. раздел 2.4.2 Использование DDD с удаленным подчиненным отладчиком, для получения подробностей.
--jdb
--ladebug
--lesstif-hacks
--lesstif-version 999
. Использовать не
рекомендуется.
Указание этого ключа эквивалентно установке ресурса DDD
`lessTifVersion' в значение 999
. См. раздел 10.19 Использование DDD с LessTif, для
получения подробностей.
--lesstif-version версия
--license
--login имя-пользователя
-l имя-пользователя
--maintenance
--manual
--news
--no-button-tips
--no-data-window
--no-debugger-console
--no-disassemble
--no-exec-window
--no-glyphs
--no-lesstif-hacks
--lesstif-version 1000
. Использовать не
рекомендуется.
Указание этого ключа эквивалентно установке ресурса DDD
`lessTifVersion' в значение 1000
. См. раздел 10.19 Использование DDD с LessTif, для
подробностей.
--no-maintenance
--no-source-window
--no-value-tips
--nw
--perl
--pydb
--panned-graph-editor
--scrolled-graph-editor
ниже.
Указание этого ключа эквивалентно установке ресурса DDD
`pannedGraphEditor' в значение `on'. См. раздел 7.3.1.12 Настройка отображений, для получения подробностей.
--play-log файл-протокола
ddd --play-log файл-протоколавызывает DDD как подчиненный отладчик, имитируя подчиненный отладчик, указанный в файле-протокола (смотрите ниже). Это полезно для отладки DDD. Указание этого ключа эквивалентно установке ресурса DDD `playLog' в значение `on'. См. раздел 2.5 Настройка диалога с подчиненным отладчиком, для дополнительной информации.
--PLAY файл-протокола
--play
.
--rhost имя-машины
--rhost имя-пользователя@имя-машины
--login
, использовать его в качестве имени удаленного
пользователя. См. раздел 2.4.2 Использование DDD с удаленным подчиненным отладчиком, для получения подробностей.
Указание этого ключа эквивалентно установке ресурса DDD
`debuggerRHost' в значение имя-машины. См. раздел 2.4.2 Использование DDD с удаленным подчиненным отладчиком, для получения подробностей.
--scrolled-graph-editor
--panned-graph-editor
ниже.
Указание этого ключа эквивалентно установке ресурса DDD
`pannedGraphEditor' в значение `off'. См. раздел 7.3.1.12 Настройка отображений, для получения подробностей.
--separate-windows
--separate
--attach
выше.
Указание этого ключа эквивалентно установке класса ресурсов DDD
`Separate' в значение `off'. См. раздел 3.6.4.2 Размещение окон, для
дополнительной информации.
--session сеанс
--source-window
--status-at-bottom
--status-at-top
--sync-debugger
--toolbars-at-bottom
--toolbars-at-top
--trace
--trace
не задан, эта информация записывается в файл
`~/.ddd/log' (`~' обозначает ваш начальный каталог),
чтобы вы могли проводить также и "посмертную" отладку.
См. раздел 10.12.1 Запись протокола, подробности о записи протокола.
Указание этого ключа эквивалентно установке ресурса DDD `trace'
в значение on. См. раздел 10.12 Получение диагностики, для получения подробностей.
--tty
-t
--value-tips
--version
-v
--vsl-library библиотека
--vsl-path путь
--vsl-help
--xdb
DDD также понимает перечисленные ниже ключи X Windows. Обратите
внимание, у этих ключей только один дефис -
.
-display дисплей
DISPLAY
.
-geometry геометрия
-iconic
-name имя
-selectionTimeout время
-title имя
-xrm строка-ресурса
Все ключи, которые DDD не распознает, передаются подчиненному отладчику. Этот раздел перечисляет наиболее полезные ключи разных подчиненных отладчиков, поддерживаемых DDD.
Эти ключи GDB полезны при использовании DDD с GDB в качестве
подчиненного отладчика. Всесто двойных дефисов --
можно также
использовать одинарные -
.
-b скорость
--cd каталог
--command файл
--core файл-дампа
--directory каталог
-d каталог
--exec выполняемый-файл
--mapped
--nx
-n
--readnow
--se файл
--symbols файл-символов
См. раздел `Вызов GDB' в Отладка с GDB, другие ключи, которые можно использовать с GDB.
Варианты DBX сильно различаются по ключам, поэтому мы не можем привести здесь список. Смотрите man-страницы dbx(1) и ladebug(1).
Данные ключи XDB полезны при использовании его в качестве подчиненного отладчика для DDD.
-d каталог
-P id-процесса
-l библиотека
-l ALL
велит делать это всегда.
-S число
-s
Другие ключи можно найти с man-странице xdb(1).
Следующие ключи JDB полезны при использовании его в качестве подчиненного отладчика для DDD.
-host имя-машины
-password пароль
-debug
).
Следующие ключи JDB передаются отлаживаемому процессу:
-verbose
-v
-debug
-noasyncgc
-verbosegc
-noclassgc
-checksource
-cs
-ss число
-oss число
-ms число
-mx число
-Dимя=значение
-classpath путь
-prof
-prof:файл
-verify
-verifyremote
-noverify
-dbgtrace
Другие ключи можно найти в документации на JDB.
Для получения списка полезных ключей PYDB смотрите его документацию.
Самый важный ключ Perl для использования с DDD -- это -w
;
он включает печать нескольких важных предупреждений. Остальные ключи
смотрите в man-странице perlrun(1).
Если у вас запущено несколько экземпляров DDD, они разделяют общие настройки и файлы истории. Это означает, что примененные к одному экземпляру изменения могут быть потеряны, когда их перезапишет другой экземпляр. DDD может защитить вас от нежелательных потерь двумя способами. Первый -- это автоматическая перезагрузка измененных параметров, управляемая следующим ресурсом (см. раздел 3.6 Настройка DDD):
30
. Установка этого ресурса в значение 0
выключает
проверку файла параметров.
Обычно автоматической перезагрузки параметров бывает достаточно. Если вам нужна более сильная защита, DDD также может выдавать предупреждение о запуске нескольких экземпляров. По умолчанию это предупреждение не выводится. Если вы хотите получать его, включите `Edit => Preferences => Warn if Multiple DDD Instances are Running'.
Эта установка привязана к такому ресурсу (см. раздел 3.6 Настройка DDD):
Если вас раздражают предупреждения X Windows, вы можете подавить их, установив `Edit => Preferences => General => Suppress X warnings'.
Данная установка привязана к следующему ресурсу (см. раздел 3.6 Настройка DDD):
Чтобы покинуть DDD, выберите `File => Exit'. Вы также
можете набрать команду quit
в подсказке отладчика или нажать
Ctrl+Q. GDB и XDB также поддерживают команду q
или знак конца файла (обычно Ctrl+D). При закрытии последнего
окна DDD также завершится.
Прерывание (ESC или `Interrupt') не закрывает DDD, а завершает действие любой работающей в данный момент команды отладчика и возвращает на командный уровень. Можно всегда безопасно ввести знак прерывания, потому что отладчик не позволяет ему подействовать до тех пор, пока это не будет безопасно.
Если обычное прерывание не срабатывает, вы можете использовать аварийный
останов (Ctrl+\ или `Abort'), что посылает подчиненному
отладчику сигнал SIGABRT
. Используйте это только в чрезвычайных
ситуациях; после этого сигнала подчиненный отладчик может оказаться в
несогласованном состоянии или даже завершиться.
В крайнем случае (например, если DDD зависает), вы можете также
прервать сам DDD, используя сигнал прерывания SIGINT
). Это
можно сделать, набрав знак прерывания (обычно это Ctrl+C) в
оболочке, откуда был запущен DDD, или с помощью команды UNIX
kill
. Этот сигнал прерывает любое действие DDD;
подчиненный отладчик также прерывается. Поскольку прерывание может
привести к внутренней несогласованности, прибегайте к нему только в
исключительных ситуациях; как можно быстрее сохраните свою работу и
перезапустите DDD.
Если вы хотите прервать текущий сеанс DDD, вы можете сохранить все состояние отладчика как сеанс на диске и продолжить работу позднее.
Чтобы сохранить сеанс, выберите `File => Save Session As'. У вас спросят символьное имя для этого сеанса.
Если ваша программа запущена (см. раздел 6. Запуск программы), или если вы открыли файл с дампом (см. раздел 4.2.2 Открывание дампов памяти), DDD также может включить в сеанс дамп памяти, с тем чтобы данные отлаживаемой программы восстанавливались после повторного открытия сеанса. Чтобы получить дамп памяти, DDD как правило должен уничтожить отлаживаемую программу. Это означает, что вы не сможете продолжить выполнение программы после сохранения сеанса. В зависимости от архитектуры могут быть доступны и другие пути получения дампа памяти.
Включение дампа необходимо для восстановления содержимого памяти и исполняемой в текущий момент позиции. Чтобы включить в сеанс дамп памяти, задействуйте `Include Core Dump'.
После щелчка на `Save' сеанс сохраняется в `~/.ddd/sessions/сеанс'.
Вот список вещей, состояние которых записывается в сеансе:
После сохранения текущего состояния сеанса он становится активным. Это означает, что состояние DDD будет сохраняться как сеанс по умолчанию:
Чтобы сделать текущий сеанс неактивным, откройте сеанс по умолчанию с именем `[None]'. См. раздел 2.3.2 Продолжение сеансов, подробности об открывании сеансов.
Чтобы продолжить сохраненный ранее сеанс, нажмите `File => Open Session' и выберите из списка имя нужного сеанса. После щелчка на `Open' будет восстановлено полное состояние DDD для указанного сеанса.
Сеанс с именем `[None]' -- это сеанс по умолчанию, который активен при запуске DDD. Чтобы сохранить параметры для сеанса по умолчанию, откройте его и запишите параметры. См. раздел 3.6.1.3 Сохранение параметров, для получения подробностей.
Если восстановленный сеанс включает дамп памяти, то отлаживаемая программа будет в том же состоянии, в каком она была во время сохранения сеанса; в частности, вы сможете исследовать данные программы. Однако, у вас не будет возможности продолжить выполнение программы, поскольку ее процесс и среда (открытые файлы, ресурсы, etc.) больше не существуют. Тем не менее, вы сможете перезапустить программу, снова используя восстановленные точки останова и отображения данных.
Открытие сеансов также восстанавливает определения команд, кнопок, операции быстрого создания отображений и размер табуляции в исходнике. Таким образом вы можете держать различные наборы определений для каждого сеанса.
Вы также можете указать, какой сеанс следует открыть, при запуске DDD. Чтобы вызвать DDD с сеансом сеанс, используйте
ddd --session сеанс
Есть также краткая форма записи, которая открывает сеанс и вызывает подчиненный отладчик для исполняемого файла с именем сеанс (в случае, если сеанс невозможно открыть):
ddd =сеанс
При перезапуске сеанса нет нужды давать другие ключи командной строки, поскольку они будут перекрыты ключами, сохраненными в сеансе.
Для записи и восстановления сеансов DDD вы также можете использовать
менеджер сеансов для X Windows, такой как xsm
.(7) Когда DDD
завершается менеджером сеансов, он сохраняет свое состояние под именем,
которое ему сообщает менеджер сеансов; восстановление X-сеанса
заставляет DDD перезагрузить сохраненное состояние.
Чтобы удалить сеансы, которые вам больше не нужны, выберите `File => Open Session' или `File => Save Session'. Выделите ненужные сеансы и щелкните на `Delete'.
Сеанс по умолчанию `[None]' нельзя удалить.
Вы можете изменить место, где DDD записывает сеансы, устанавливая
переменную среды DDD_SESSIONS
равной имени каталога. По умолчанию
принимается `~/.ddd/sessions/'.
Когда это применимо, DDD поддерживает команду gcore
, которая
служит для получения файла с дампом памяти работающей программы. Вы
можете ввести путь этой команды через `Edit => Preferences
=> Helpers => Get Core File'. Оставьте значение пустым,
если у вас нет gcore
или подобной программы.
Данная установка привязана к следующему ресурсу (см. раздел 3.6 Настройка DDD):
gcore
) `@FILE@' заменяется на базовое имя создаваемого
файла; `@PID@' заменяется на ID процесса. Вывод должен быть
записан в `@FILE@.@PID@'.
Оставьте значение пустым, если у вас нет gcore
или подобной
программы.
Вы можете запустить DDD, подчиненный отладчик и отлаживаемую программу на разных машинах.
Вы можете запустить DDD на удаленной машине, используя текущую машину в качестве X-дисплея. Для вызова DDD на удаленной машине наберите
ddd -display дисплей
где дисплей -- это имя X-сервера, к которому следует подсоединиться (например, `имя-машины:0.0', где имя-машины -- это имя вашей машины).
Вместо указания ключа -display дисплей
вы также можете
установить переменную среды DISPLAY
равной дисплею.
Чтобы запустить подчиненный отладчик на удаленной машине, вам требуется доступ к этой машине по `remsh' (в системах BSD это называется `rsh').
Для запуска отладчика на удаленной машине имя-машины, вызовите DDD как
ddd --host имя-машины удаленная-программа
Если удаленное имя пользователя отличается от локального, используйте
ddd --host имя-машины --login имя-пользователя удаленная-программа
или
ddd --host имя-пользователя@имя-машины удаленная-программа
В удаленном режиме отладки есть несколько трудных мест:
--rhost
вместо
--host
. Тогда удаленный отладчик будет запущен через
интерактивную оболочку на удаленной машине, что может улучшить ситуацию.
Замечание: при использовании --rhost
, DDD вызывает
подчиненный отладчик, как только появляется подсказка оболочки. Первый
кусок вывода на удаленной машине, завершающийся пробелом или знаком
`>', и после которого не следует перевод строки, считается
подсказкой оболочки. Если необходимо, настройте подсказку оболочки на
удаленной машине.
xterm
, передавая в качестве адреса текущее
значение переменной среды DISPLAY
. Если удаленная машина не может
запустить xterm
или не имеет доступа к вашему X-дисплею,
запустите DDD с ключом --no-exec-window
. Тогда ввод/вывод
программы будет идти через консоль отладчика DDD.
--trace
. Тогда отдаваемые DDD команды
оболочки печатаются на стандартный поток ошибок.
См. раздел 2.4.2.1 Настройка удаленной отладки, о настройке удаленного режима.
Когда вы запускаете подчиненный отладчик на удаленной машине (см. раздел 2.4 Удаленная отладка), все команды для обращения к подчиненному отладчику и его файлам должны запускаться удаленно. Этим управляют следующие ресурсы (см. раздел 3.6 Настройка DDD):
remsh
, rsh
, ssh
или
on
.
Ddd*listCoreCommand: \ file @MASK@ | grep '.*:.*core.*' | cut -d: -f1
Ddd*listDirCommand: \ file @MASK@ | grep '.*:.*directory.*' | cut -d: -f1
Ddd*listExecCommand: \ file @MASK@ | grep '.*:.*exec.*' \ | grep -v '.*:.*script.*' \ | cut -d: -f1 | grep -v '.*\.o$'
Ddd*listSourceCommand: \ file @MASK@ | grep '.*:.*text.*' | cut -d: -f1
Отладчик GDB позволяет вам запускать отлаживаемую программу на удаленной машине (называемой удаленной целью), тогда как GDB работает на локальной машине.
См. раздел `Remote Debugging' в Debugging with GDB, для получения подробностей. В двух словах, требуются следующие шаги:
gdbserver
.
file
.
target remote
.
Локальный файл `.gdbinit' полезен для подготовки путей поиска, etc.
Разумеется, вы можете также комбинировать удаленные режимы DDD и GDB, запуская DDD, GDB и отлаживаемую программу на разных машинах.
Перечисленные ниже установки управляют диалогом DDD с его подчиненным отладчиком.
Чтобы выбрать используемый по умолчанию отладчик, выберите `Edit => Preferences => Startup => Debugger Type'. Вы можете сделать так, чтобы
Следующие ресурсы DDD управляют вызовом подчиненного отладчика (см. раздел 3.6 Настройка DDD).
Данный ресурс обычно устанавливается через ключи --gdb
,
--dbx
, --ladebug
, --xdb
, --jdb
,
--pydb
и --perl
; См. раздел 2.1.2 Ключи DDD, для получения подробной
информации.
Данный ресурс обычно устанавливается через ключ --debugger
;
См. раздел 2.1.2 Ключи DDD, для получения подробной информации.
DDD использует несколько ресурсов для инициализации подчиненного отладчика (см. раздел 3.6 Настройка DDD).
Ddd*gdbInitCommands: \ set height 0\n\ set width 0\n\ set verbose off\n\ set prompt (gdb) \n
Тогда как установки `set height', `set width' и `set prompt' фиксированы, установку `set verbose' можно изменить из панели настройки GDB (хотя это сбрасываться при каждом запуске DDD).
Не используйте этот ресурс для настройки GDB; вместо этого, напишите персональный файл `~/.gdbinit'. Подробности смотрите в документации по GDB.
Ddd*gdbSettings: \ set print asm-demangle on\n
Этот ресурс используется для записи и восстановления установок отладчика.
Не используйте этот ресурс для настройки DBX; вместо этого, напишите персональный файл `~/.dbxinit' или `~/.dbxrc'. Подробности смотрите в документации по DBX.
Не используйте этот ресурс для настройки XDB; вместо этого, напишите персональный файл `~/.xdbrc'. Подробности смотрите в документации по XDB.
DDD использует этот ресурс для записи и восстановления установок JDB.
Этот ресурс можно использовать для настройки PYDB.
DDD использует этот ресурс для записи и восстановления установок PYDB.
Этот ресурс можно использовать для настройки отладчика Perl.
DDD использует этот ресурс для записи и восстановления установок отладчика Perl.
main
. Если такая позиция не найдена, DDD пробует другие
символы из этого разделенного переводами строки списка. Значение,
которое принимается по умолчанию, велит DDD искать различные варианты
главной функции (в особенности главные функции Фортрана):
main\n\ MAIN\n\ main_\n\ MAIN_\n\ main__\n\ MAIN__\n\ _main\n\ _MAIN\n\ __main\n\ __MAIN
Следующие ресурсы управляют общением с подчиненным отладчиком.
2000
.
500
.
10
.
--sync-debugger
.
tty
для
перенаправления ввода/вывода в отдельное окно выполнения. Если
`off', использовать явное перенаправление посредством операторов
перенаправления оболочки `<' и `>'. По умолчанию `off'
(явное перенаправление), так как на некоторых системах и в некоторых
версиях GDB команда tty
работает неправильно.
DDD составлен из трех основных окон. Снизу вверх:
Кроме этих трех главных окон есть еще несколько дополнительных:
Полоска меню DDD предоставляет доступ ко всем функциям DDD.
File
Edit
View
Program
Commands
Status
Source
Data
Maintenance
Help
Есть два способа выбрать элемент из ниспадающего меню:
Меню также можно отцепить (то есть превратить в постоянное окно), выбрав штриховую линию сверху меню.
Если команда из ниспадающего меню не применима в данной ситуации, то эта команда выключена, а ее имя выводится затененным. Вы не можете вызывать затененные пункты меню. Например, многие команды в меню `Edit' затенены, пока вы не выделите текст, на который они могут действовать; когда вы выделяете блок текста, команды редактирования включаются.
Меню `File' содержит операции, относящиеся к файлам, такие как выбор программ, процессов и сеансов, печать графов, перекомпиляция, а также выход из DDD.
Open Program
Open Class
Open Recent
Open Core Dump
Open Source
Open Session
Save Session As
Attach to Process
Detach Process
Print Graph
Change Directory
Make
make
. См. раздел 9.2 Перекомпиляция, для
получения подробностей.
Close
Restart
Exit
Меню `Edit' содержит стандартные операции редактирования, такие как вырезка, копирование, вставка и уничтожение выделенного текста. Оно также позволяет редактировать параметры DDD и пользовательские предпочтения.
Undo
Redo
Cut
Copy
Paste
Clear
Delete
Select All
Preferences
Debugger Settings
Save Options
Меню `View' позволяет получать доступ к отдельным окнам DDD.
Command Tool
Execution Window
Debugger Console
Source Window
Data Window
Machine Code Window
Меню `Program' производит операции, относящиеся к отлаживаемой программе, такие как запуск и останов.
Большинство этих команд также есть в панели команд (см. раздел 3.3 Панель команд).
Run
Run Again
Run in Execution Window
Step
Step Instruction
Next
Next Instruction
Until
Finish
Continue
Continue Without Signal
Kill
Interrupt
Abort
SIGABRT
. См. раздел 2.2 Выход из DDD,
для получения подробностей.
Меню `Commands' производит операции, относящиеся к командам DDD, такие как доступ к истории или определение новых команд.
Большая часть его пунктов на самом деле не предназначены для выполнения через меню; они просто служат для напоминания об эквивалентных командах клавиатуры.
Command History
Previous
Next
Find Backward
Find Forward
Quit Search
Complete
Apply
Clear Line
Clear Window
Define Command
Edit Buttons
Меню `Status' позволяет вам узнать состояние программы, например, просмотреть следы вызовов, регистры или нити.
Backtrace
Registers
Threads
Signals
Up
Down
Меню `Source' производит операции, относящиеся к исходному коду, такие как поиск объектов или редактирование точек останова.
Breakpoints
Lookup ()
Find >> ()
Find << ()
Find Words Only
Find Case Sensitive
Display Line Numbers
Display Machine Code
Edit Source
Reload Source
Меню `Data' производит операции, относящиеся к данным, такие как редактирование отображений или размещение объектов в графе данных.
Displays
Watchpoints
Memory
Print ()
Display ()
Detect Aliases
Display Local Variables
Display Arguments
Status Displays
Align on Grid
Rotate Graph
Layout Graph
Refresh
Меню `Maintenance' производит операции, которые полезны для отладки DDD.
По умолчанию это меню выключено; включить его можно, специально запросив
при запуске DDD (с помощью ключа --maintenance
;
см. раздел 2.1.2 Ключи DDD). Оно также включается, когда DDD получает фатальный
сигнал.
Debug DDD
Dump Core Now
SIGUSR1
.
Tic Tac Toe
When DDD Crashes
Debug DDD
Dump Core
Do Nothing
Remove Menu
Меню `Help' дает справку по использованию DDD. См. раздел 3.4 Получение справки, как получить справку из DDD.
Overview
On Item
On Window
What Now?
Tip of the Day
DDD Reference
DDD News
Debugger Reference
DDD License
DDD WWW Page
About DDD
Полоску меню можно настраивать разными способами (см. раздел 3.6 Настройка DDD).
Можно сделать так, чтобы ниспадающие меню поднимались автоматически.
100
.
Меню `Edit' можно по-разному настраивать. Для настройки ключей используйте `Edit => Preferences => Startup'.
Ключ Ctrl+C можно привязать к разным действиям, каждое соответствует своему стандарту интерфейса.
Copy
Interrupt
Ctrl+A тоже можно привязать к разным действиям.
Select All
Beginning of Line
Вот соответствующие ресурсы DDD:
Некоторые команды DDD требуют аргумента. Аргумент задается в поле аргумента, помеченном как `():'. Есть четыре основных способа задавать аргументы:
При использовании GDB или Perl поле аргумента предоставляет механизм завершения. Вы можете ввести несколько первых знаков и нажать клавишу TAB для завершения. Повторное нажатие TAB покажет другие варианты завершения.
После ввода аргумента вы можете выбрать одну из трех кнопок справа. С большей частью этих кнопок совмещены меню; это обозначается маленькой стрелкой в верхнем правом углу. Нажатие и удержание на такой кнопке первой кнопки мыши вызовет меню дальнейших операций.
Это кнопки на панели инструментов. Заметьте, что не все кнопки могут быть неактивными, в зависимости от текущего состояния и возможностей подчиненного отладчика.
Lookup
Find >>
Break/Clear
Break
Clear
Watch/Unwatch
Watch
Unwatch
Print
Display
Plot
Show/Hide
Rotate
Set
Undisp
Кнопки панели инструментов DDD могут отображаться в различных стилях, это настраивается через `Edit => Preferences => Startup'.
Images
Captions
По умолчанию показываются и рисунки, и названия, но вы можете выбрать только рисунки (для экономии места) или только названия.
Если вы предпочли не выводить ни рисунков, ни названий, кнопки панели инструментов помечаются так же, как другие кнопки, как в DDD 2.x. Обратите внимание: это подразумевает, что при совмещенной конфигурации окон обычная панель инструментов не может отображаться; она заменяется на две отдельные панели инструментов, как в DDD 2.x.
Если вы включите кнопки `Flat' (по умолчанию), то рамка кнопок панели инструментов будет появляться только тогда, когда над ними находится указатель мыши. Это последнейшее и величайшее изобретение в области графических интерфейсов можно выключить, чтобы рамка кнопок показывалась всегда.
Если вы включите кнопки `Color', рисунки панели инструментов будут расцвечиваться, когда на них заходит указатель мыши. Если DDD собран с Motif 2.0 или более поздним, вы можете также выбрать третью установку, когда кнопки всегда цветные.
Вот соответствующие ресурсы (см. раздел 3.6 Настройка DDD):
Панель команд -- это маленькое окно, дающее доступ к самым часто используемым командам DDD. Его можно передвигать поверх окон DDD, но можно и поместить отдельно от них.
По умолчанию панель команд прикрепляется к окну DDD с исходным текстом: куда бы вы не передвинули это окно, панель команд последует за ним, так что расстояние от окна исходного текста до панели команд остается постоянным. Кроме того, по умолчанию панель команд автоматически поднята, то есть всегда остается поверх других окон DDD.
Панель команд можно настроить так, чтобы она отображалась в виде командной полоски меню в верхней части окна исходника; смотрите `Edit => Preferences => Source => Tool Buttons Location' для получения подробностей.
Всякий раз при сохранении состояния DDD, запоминается также расстояние от панели команд до окна исходного текста, так что вы можете выбрать свое собственное предпочтительное расположение панели. Для перемещения панели команд к сохраненной позиции используйте `View => Command Tool'.
Это кнопки панели команд. Заметьте, что некоторые кнопки могут быть неактивными, в зависимости от текущего состояния и возможностей подчиненного отладчика.
Run
Interrupt
Step
Stepi
Next
Nexti
Until
Finish
Cont
Kill
Up
Down
Undo
Redo
Edit
Make
make
с последними заданными аргументами.
См. раздел 9.2 Перекомпиляция, для дополнительной информации.
Панель команд можно по-разному настраивать.
См. раздел 10.4.1 Настройка кнопок, для получения информации о настройке командных кнопок.
Вы можете выключить панель команд и вынести ее кнопки на отдельную строку под полоской меню. Панель команд выключается установкой `Edit => Preferences => Source => Tool Buttons Location => Source Window'.
Вот соответствующие ресурсы:
Следующие ресурсы управляют позицией панели команд (см. раздел 3.6 Настройка DDD):
Следующие ресурсы управляют оформлением панели команд (см. раздел 3.6 Настройка DDD):
В DDD есть обширная интерактивная справочная система. Здесь описывается, как получить справку, работая в DDD.
help
. См. раздел 10.1 Ввод команд, для получения
подробностей о вводе команд.
Все эти функции можно по-разному настраивать (см. раздел 3.6.2 Настройка справки DDD).
Если все-таки вы допустили ошибку, не беспокойтесь: почти все команды DDD можно отменить. См. раздел 3.5 Отмена и возврат команд, для дополнительной информации.
Почти любую команду DDD можно отменить, используя `Edit => Undo' или кнопку `Undo' из панели команд.
Аналогично, `Edit => Redo' повторяет последнюю отмененную команду.
Меню `Edit' показывает, какие команды будут отменены или повторены следующими; это также указывается во всплывающей справке для кнопок `Undo' и `Redo'.
DDD контролируется несколькими ресурсами -- определяемыми пользователем переменными, которым можно придавать особые значения для управления поведением DDD и его настройки.
Большинство ресурсов DDD можно установить интерактивно, когда DDD работает, или при запуске DDD. См. раздел Указатель ресурсов, полный список ресурсов DDD.
Сначала мы обсудим работу настройки вообще; потом перейдем к настройке тех частей DDD, о которых уже говорилось.
Подобно любой программе для X Windows, DDD может получить значения ресурсов из нескольких источников. Для DDD, наиболее важными являются такие:
DDD_STATE
, вместо
`~/.ddd/' используется ее значение.
DDD_SESSION
, то она обозначает
имя сеанса, который следует начать, и перекрывает все ключи и ресурсы.
Это применяется, только когда DDD перезапускает сам себя.
Не для каждого ресурса есть соответствующий ключ командной строки. Каждый ресурс (в файле `~/.ddd/init' или `Ddd') определяется с помощью строки
Ddd*ресурс: значение
Например, чтобы установить ресурс `pollChildStatus' в значение `off', вы написали бы в файле `~/.ddd/init' так:
Ddd*pollChildStatus: off
Подробности о синтаксисе спецификаций ресурсов вы можете найти в разделе RESOURCES страницы man X(1).
Вы можете изменить ресурсы DDD тремя способами:
Вы можете сохранить текущие установки параметров, выбрав `Edit => Save Options'. Параметры записываются в файл с именем `.ddd/init' в вашем начальном каталоге. Если активен сеанс сеанс, то параметры сохраняются в файле `~/.ddd/sessions/сеанс/init'.
Справочную систему DDD можно по-разному настраивать.
Подсказки для кнопок помогают новичкам, но могут отвлекать опытных пользователей. Вы можете выключить всплывающие подсказки через `Edit => Preferences => General => Automatic display of Button Hints => as Popup Tips'.
Вы можете также выключить подсказки, отображаемые в строке состояния. Просто переключите `Edit => Preferences => General => Automatic Display of Button Hints => in the Status Line'.
Вот соответствующие ресурсы DDD (см. раздел 3.6 Настройка DDD):
Вы можете выключить совет дня, переключив `Edit => Preferences => Startup => Startup Windows => Tip of the Day'.
Соответствующий ресурс DDD (см. раздел 3.6 Настройка DDD):
См. раздел 2.1.2 Ключи DDD, как установить этот ресурс из командной строки при запуске DDD.
Сами советы контролируются следующими ресурсами (см. раздел 3.6 Настройка DDD):
DDD полагается на несколько внешних программ, которые задаются через `Edit => Preferences => Helpers'.
Для декомпрессии справочных текстов вы можете определить команду `Uncompress':
gzip -d -c
; другие типичные значения включают zcat
и
gunzip -c
.
Для просмотра веб-страниц вы можете определить команду `Web Browser':
mozilla
, затем netscape
),
потом $WWWBROWSER
, потом DDD пытается запустить новый
процесс Netscape, потом пробуется запущенный Emacs, потом вызывается
Mosaic, а потом Lynx в xterm.
Чтобы указать в качестве броузера `netscape-4.0', используйте такую установку:
Ddd*wwwCommand: \ netscape-4.0 -remote 'openURL(@URL@)' \ || netscape-4.0 '@URL@'
Эта команда сначала пытается соединиться с работающим броузером
netscape-4.0
; если это не получается, она запускает новый процесс
netscape-4.0
.
Это WWW-страница, которая показывается по умолчанию командой `Help ' DDD WWW Page:
Отмену команд можно настраивать в нескольких аспектах.
Чтобы установить максимальный размер буфера отмены, установите `Edit => Preferences => General => Undo Buffer Size'.
Это соответствует ресурсу `maxUndoSize':
2000000
, или 2000
килобайт.
Вы можете также ограничить число вхождений в буфере отмены, безотносительно его размера (см. раздел 3.6 Настройка DDD):
Чтобы очистить буфер отмены в любое время, уменьшив таким образом объем занятой памяти, используйте `Edit => Preferences => General => Clear Undo Buffer'.
Окна DDD можно по-разному настраивать.
Вы можете выключить заставку, которая показывается при запуске. Для этого просто выберите `Edit => Preferences => Startup DDD Splash Screen'.
Это значение применяется только к следующему запуску DDD.
С этой установкой связан следующий ресурс:
Вы можете также управлять внешним видом заставки (см. раздел 3.6 Настройка DDD):
Пожалуйста, обратите внимание: если DDD работает на монохромном дисплее, или если DDD был скомпилирован без библиотеки @acronym{XPM}, может отображаться только монохромная версия (`m').
По умолчанию DDD объединяет команды, исходный код и данные в единое окно верхнего уровня. Чтобы получить отдельные окна верхнего уровня для исходника, данных и консоли отладчика, установите `Edit => Preferences => Startup => Window Layout => Separate Windows'.
Соответствующие ресурсы DDD:
По умолчанию панели инструментов DDD располагаются в верхней части окна. Если вы предпочитаете, чтобы они находились внизу, как в DDD 2.x и более ранних версиях, установите `Edit => Preferences => Startup => Tool Bar Appearance => Bottom'.
С этой установкой связан ресурс `toolbarsAtBottom':
Размещение внизу поддерживается только для отдельных панелей инструментов -- то есть, вы должны либо выбрать раздельные окна, либо сконфигурировать панель инструментов так, чтобы в ней не было ни рисунков, ни названий (см. раздел 3.2.1 Настройка панели инструментов).
Если вы используете соединенные окна, вы можете сделать одну панель инструментов или две. По умолчанию DDD создает две панели инструментов при использовании раздельных окон и выключенных названиях и рисунках, но вы также можете явно изменить данную установку через такой ресурс:
Вы также можете изменить позицию строки состояния (см. раздел 3.6 Настройка DDD):
См. раздел 2.1.2 Ключи DDD, как установить эти ресурсы из командной строки при запуске DDD.
Вы можете конфигурировать основные шрифты DDD в время работы. Каждый шрифт задается с помощью двух элементов:
Чтобы указать шрифты, выберите `Edit => Preferences => Fonts'.
Кнопка `Browse' открывает программу выбора шрифтов, где вы можете интерактивно подбирать шрифты и их атрибуты. Щелчок на `quit' или `select' передает все отличающиеся от принимаемых по умолчанию значения в панель настройки шрифтов DDD.
Используя эту панель, можно установить следующие шрифты:
Default Font
Variable Width
Fixed Width
Изменения в этой панели не имеют мгновенного эффекта. Вы можете
Когда в этой панели делаются изменения, DDD автоматически предложит вам перезапустить себя, чтобы эти изменения подействовали. Заметьте, что даже после перезапуска вы должны будете сохранить параметры, чтобы ваши изменения стали постоянными.
Кнопка `Reset' восстанавливает последние сохраненные предпочтения.
Вот ресурсы, связанные с заданием шрифтов:
Значение по умолчанию -- `helvetica-bold'.
Чтобы установить шрифт DDD по умолчанию равным, скажем, `helvetica medium', вставьте строку
Ddd*defaultFont: helvetica-medium
в ваш файл `~/.ddd/init'.
120
, что задает двенадцатипунктовый шрифт.
Значение по умолчанию равно `helvetica-medium-r'.
Чтобы установить семейство пропорционального шрифта DDD равным, скажем, `times', вставьте строку
Ddd*fixedWidthFont: times-medium
в ваш файл `~/.ddd/init'.
120
, что задает двенадцатипунктовый шрифт.
Значение по умолчанию -- `lucidatypewriter-medium'.
Чтобы установить семейство равноширинного шрифта DDD равным, скажем, `courier', вставьте строку
Ddd*fixedWidthFont: courier-medium
в ваш файл `~/.ddd/init'.
120
, что задает двенадцатипунктовый шрифт.
Поскольку все ресурсы для задания размеров шрифтов принадлежат одному классу (и по умолчанию имеют одинаковое значение), вы можете легко изменить размер шрифта DDD по умолчанию на, скажем, 9.0 пунктов, вставив строку
Ddd*FontSize: 90
в свой файл `~/.ddd/init'.
Команда для выбора шрифтов задается так:
Ddd*fontSelectCommand: xfontsel -print
См. раздел 2.1.2 Ключи DDD, как установить эти ресурсы из командной строки при запуске DDD.
Когда окна объединены, как в установке по умолчанию, вы можете включать и выключать отдельные окна DDD переключая соответствующие пункты меню `View' (см. раздел 3.1.3 Меню View). При использовании раздельных окон см. раздел 3.6.4.2 Размещение окон) вы можете закрывать их через `File => Close' или с помощью вашего оконного менеджера.
Следующие ресурсы управляют тем, открыты окна или нет при запуске DDD. Эти ресурсы непосредственно привязаны к пунктам меню `View':
См. раздел 2.1.2 Ключи DDD, как установить эти ресурсы из командной строки при запуске DDD.
Текстовые поля DDD можно настраивать с помощью следующих ресурсов:
0
(по умолчанию) означает, что ограничения нет.
Если вы часто переключаетесь между DDD и другими многооконными приложениями, вы можете захотеть установить `Edit => Preferences => General => Iconify all windows at once'. Тогда все окна DDD сворачиваются и разворачиваются вместе.
Это привязано к такому ресурсу:
Если вы хотите убирать DDD с рабочего стола во время долгих вычислений, вы можете установить `Edit => Preferences => General => Uniconify when ready'. Тогда можно будет свернуть DDD на время, пока он занят выполнением команды (например, прогоном программы); DDD автоматически развернется, когда станет готов принимать другие команды (например, после того, как отлаживаемая программа достигнет точки останова). См. раздел 6.4 Остановы программы, обсуждение этой темы.
Связанный с этой установкой ресурс:
Вы можете добавлять в DDD новые кнопки. См. раздел 10.4 Определение кнопок, для получения подробностей.
Вы можете изменить буквально любую метку, цвет, привязку клавиши и так далее, изменяя ресурсы из файла `Ddd', который поставляется с дистрибутивом исходного кода DDD. Это работает так:
См. раздел A. Ресурсы по умолчанию, подробности о файле ресурсов по умолчанию.
Вы можете изменить внутренние установки для большинства подчиненных отладчиков с помощью `Edit => Settings'. Используя редактор установок, можно определить, следует ли приводить к обычному виду имена в Си++, сколько элементов массива нужно печатать и так далее.
Возможности редактора установок зависят от возможностей вашего подчиненного отладчика. Щелчок на `?' даст объяснение отдельных пунктов; более подробные сведения можно найти в документации на GDB.
Для отмены изменений используйте `Edit => Undo'. Щелчок на `Reset' восстанавливает последние сохраненные установки.
Некоторые установки отладчика нечувствительны, и их нельзя изменить, поскольку это подвергло бы опасности работоспособность DDD. Для получения подробностей смотрите описания ресурсов `gdbInitCommands' и `dbxInitCommands'.
Все установки отладчика (кроме путей исходных и объектных файлов) сохраняются вместе с параметрами DDD.
В данной главе обсуждается, как получить доступ к исходному коду из DDD.
Чтобы эффективно отлаживать программу, вам необходимо сгенерировать при компиляции отладочную информацию. Эта отладочная информация записывается в объектном файле; она описывает тип данных каждой переменной или функции и соответствие между номерами строк в исходном тексте и адресами в исполняемом файле.(9)
Чтобы затребовать создание отладочной информации, укажите при запуске
компилятора ключ -g
.
Многие компиляторы Си не могут одновременно обрабатывать ключи
-g
и -O
. При использовании таких компиляторов вы не
сможете генерировать оптимизированные исполняемые файлы с отладочной
информацией.
@acronym{GCC}, компилятор Си GNU, поддерживает ключ -g
с
-O
и без, что позволяет отлаживать оптимизированный код. Мы
рекомендуем всегда использовать ключ -g
при компиляции
программы. Вы можете считать, что ваша программа корректна, но нет
смысла испытывать удачу.
Когда вы отлаживаете программу, скомпилированную с -g -O
,
помните, что оптимизатор переорганизует ваш код; отладчик показывает то,
что есть на самом деле. Не удивляйтесь, когда поток выполнения не
совсем соответствует исходному файлу! Пример крайнего случая: если вы
определяете переменную, но нигде ее не используете, DDD не увидит эту
переменную -- потому что компилятор ее выбросил.
Если вы запустили DDD, не указав отлаживаемую программу, вы можете использовать меню `File' для открывания программ, дампов памяти и исходных файлов.
Чтобы открыть программу для отладки, выберите `File => Open Program'.(10) Чтобы открыть программу, щелкните на `Open'.
Если вы отлаживаете в JDB, выберите `File => Open Class'. Вы получите список доступных классов.
Чтобы открыть программу или класс, которые вы уже недавно отлаживали, выберите `File => Open Recent' и укажите программу или класс из списка.
См. раздел 4.3.4 Указание каталогов с исходными файлами, как задать каталоги исходных файлов, если исходные файлы не найдены.
Если предыдущий прогон программы завершился крахом, и вы хотите выяснить почему, вы можете исследовать в DDD дамп памяти этой программы.(11)
Чтобы открыть дамп памяти программы, выберите `File => Open Core Dump'. Для открывания дампа щелкните на `Open'.
Перед использованием `Open Core Dump' вы должны сначала выбрать `File => Open Program' и указать программу, которая сбросила дамп, и загрузить ее таблицу символов.
Чтобы открыть исходный файл отлаживаемой программы, выберите `File => Open Source'.
Чтобы открыть исходный файл, щелкните на `Open'. См. раздел 4.3.4 Указание каталогов с исходными файлами, если исходные файлы не найдены.
Когда DDD предоставляет список файлов для выбора, при открывании исполняемых файлов, дампов памяти или исходных файлов он по умолчанию фильтрует файлы, так что показываются только подходящие. Для этого DDD должен открывать каждый файл, что может занять некоторое время. См. раздел 4.4.6 Настройка фильтрации файлов, если вы хотите выключить эту возможность.
Когда исходный файл отлаживаемой программы становится доступен, в окне исходного кода показывается его текущий текст. (см. раздел 4.3.4 Указание каталогов с исходными файлами, если исходный текст не найден.)
В этом окне вы можете искать и исследовать определения функций и переменных, а также искать появления произвольного текста.
Если вы хотите найти определение какой-то конкретной функции или переменной, чье имя видимо в исходном тексте, щелкните на имени этой функции или переменной первой кнопкой мыши. Имя скопируется в поле аргумента. Измените его, если необходимо, и щелкните на кнопке `Lookup', чтобы найти определение.
Есть более быстрый способ: вы можете просто нажать на имени функции третью кнопку мыши и выбрать во всплывающем меню пункт `Lookup'.
Другой способ, еще быстрее: чтобы найти определение функции, дважды щелкните на ее вызове (это идентификатор, после которого стоит знак `(').
Если исходный файл не найден, См. раздел 4.3.4 Указание каталогов с исходными файлами, о том, как указать каталоги с исходными файлами.
Если объект, который вы хотите найти, виден в исходном тексте, щелкните на нем первой кнопкой мыши. Идентификатор будет скопирован в поле аргумента. Потом щелкните на кнопке `Find >>', чтобы найти следующие появления, или `Find >> => Find << ()', чтобы найти предыдущие появления.
По умолчанию DDD находит только полные слова. Для поиска произвольной подстроки измените значение параметра `Source => Find Words Only'.
Чтобы вернуться к начальной позиции после поиска, используйте `Edit => Undo' (или кнопку `Undo' в панели команд). `Edit => Redo' возвращает снова к найденной позиции.
Иногда в исполняемых программах не записываются каталоги исходных файлов, использовавшихся для компиляции, а записаны только имена файлов. Даже когда каталоги записаны, со времени компиляции их могли переместить.
Ниже описан способ, который применяется в GDB для обращения к исходным файлам; другие подчиненные отладчики пользуются сходными методами.
В GDB есть список каталогов, которые следует просматривать при поиске исходных файлов; он называется путем исходных файлов. Каждый раз, когда GDB нужен исходный файл, он пробует все каталоги из этого списка, в том порядке, в котором они в нем записаны, пока не найдет нужное имя. Заметьте, что путь исполняемых файлов не используется для этой цели. Не используется и текущий рабочий каталог, если только он не окажется в пути исходных файлов.
Если GDB не может найти файл по пути исходных файлов, а в объектной программе записан каталог, тогда GDB пробует его. Если путь исходных файлов пуст, а каталог компиляции не записан, GDB напоследок ищет в текущем каталоге.
Чтобы указать подчиненному отладчику путь исходных файлов, используйте `Edit => Debugger Settings' (см. раздел 3.6.5 Установки отладчика) и отредактируйте соответствующие поля (для GDB это `Search path for source files').
Если в `Debugger Settings' нет подходящего вхождения, вы можете задать путь исходных файлов при запуске DDD. См. раздел 2.1.4 Ключи подчиненного отладчика, для получения подробностей.
При использовании JDB вы можете установить переменную среды
CLASSPATH
для указания каталогов, где JDB (и DDD) должны
искать классы.
Если DDD по какой-либо причине не находит исходный файл, проверьте такие варианты:
-g
. См. раздел 4.1 Компиляция для отладки, для получения подробностей.
directory путь
.
Здесь путь -- это разделенный двоеточиями список исходных
каталогов.
Окно исходного кода можно по-разному настраивать, в основном через `Edit => Preferences => Source'.
Текущая выполняемая позиция и точки останова отмечаются в исходном тексте графическими символами (глифами). В качестве альтернативы, DDD может показывать такие позиции с помощью текстовых знаков. Если вы хотите выключить глифы, установите параметр `Edit => Preferences => Source => Show Position and Breakpoints => as Text Characters'. Это также слегка ускоряет работу DDD, особенно прокрутку.
Эта установка связана со следующим ресурсом:
--glyphs
и --no-glyphs
.
Вы можете более детально контролировать отображение глифов с помощью таких ресурсов:
10
.
10
).
Повышение этой величины приводит к резервированию большего числа глифов
и, возможно, бессмысленной трате ресурсов.
Поиск в исходном тексте (см. раздел 4.3.2 Текстуальный поиск) управляется посредством следующих ресурсов, которые можно изменить через меню `Source':
DDD может показывать в окне исходного кода номера строк. Используйте `Edit => Preferences => Source => Display Source Line Numbers'.
Вы можете велеть DDD делать в исходном коде отступы, оставляя больше
места для точек останова и глифов выполнения. Это делается с помощью
ползунка `Edit => Preferences => Source =>
Source indentation'. По умолчанию принимается значение 0
, то
есть отступы вообще не делаются.
0
.
По умолчанию DDD использует минимальный отступ для языков сценариев.
4
.
Максимальная ширина номеров строк контролируется следующим ресурсом.
4
.
Если в вашем исходном коде ширина знаков табуляции отличается от восьми (как по умолчанию), вы можете установить другую ширину, используя ползунок `Edit => Preferences => Source => Tab width'.
8
)
Следующие ресурсы говорят, когда прокручивается окно исходного кода:
2
.
3
.
Некоторые варианты DBX и XDB неправильно обрабатывают пути в спецификациях исходных файлов. Если вы хотите, чтобы подчиненный отладчик ссылался на исходные позиции только по базовым именам файлов, снимите установку `Edit => Preferences => Source => Refer to Program Sources by full path name'.
С этим связан следующий ресурс:
По умолчанию DDD кеширует исходные файлы в памяти. Это удобно для удаленной отладки, поскольку удаленный доступ к файлам может быть медленным. Если вы хотите уменьшить потребление памяти, снимите установку `Edit => Preferences => Source => Cache source files'.
С этим связан следующий ресурс:
Вы можете указать DDD, следует ли фильтровать файлы перед открыванием.
DDD предоставляет несколько средств для исследования данных.
Чтобы увидеть значение простой переменной, поместите указатель мыши над ее именем. Спустя секунду всплывет маленькое окно (называемое подсказкой для значения), показывающее значение этой переменной. Окно исчезает, как только вы уберете указатель с имени переменной. Значение также показывается в строке состояния.
Подсказки для значений можно выключить через `Edit => Preferences => General => Automatic display of variable values as popup tips'.
Показ значений в строке состояния выключается через `Edit => Preferences => General => Automatic display of variable values in the status line'.
Эти настройки привязаны к следующим ресурсам:
Значение переменной можно также напечатать в консоли отладчика, что делает его доступным для будущих операций. Чтобы напечатать значение какой-то переменной, выберите ее, щелкнув первой кнопкой мыши на ее имени. Имя переменной будет скопировано в поле аргумента. Если теперь щелкнуть на кнопке `Print', значение напечатается в консоли отладчика. Кроме того, значение показывается в строке состояния.
Есть более быстрый вариант: вы можете просто нажать на имени переменной третью кнопку мыши и выбрать из всплывающего меню пункт `Print'.
При использовании GDB кнопка `Print' генерирует команду
print
, у которой есть еще несколько параметров. См. раздел `Examining Data' в Debugging with GDB,
о специфичных для GDB выражениях, переменных и выходных форматах.
Чтобы исследовать сложные структуры данных, вы можете отобразить их в окне данных. Окно данных отображает избранные данные вашей программы, графически изображая сложные структуры. Оно обновляется при каждом останове программы.
В этом разделе рассказывается как создавать и удалять отображения и манипулировать ими. Базовые операции:
Чтобы создать новое отображение, показывающее некую переменную, выберите эту переменную, щелкнув на ее имени первой кнопкой мыши. Имя переменной будет скопировано в поле аргумента. Если теперь щелкнуть на кнопке `Display', в окне данных появится новое отображение. Окно данных открывается автоматически, как только вы создаете отображение.
Есть более короткий способ: вы можете просто нажать на имени переменной третью кнопку мыши и выбрать из всплывающего меню пункт `Display'.
В качестве еще более быстрого способа, можно также дважды щелкнуть на имени переменной.
Еще один способ: можно ввести выражение, которое нужно отобразить, в поле аргумента и нажать кнопку `Display'.
И наконец: вы также можете набрать команду в подсказке отладчика:
graph display выражение [clustered] [at (x, y)] [dependent on отображение] [[now or] when in область]
Эта команда создает новое отображение, показывающее значение указанного выражения. Необязательные части означают следующее:
clustered
at (x, y)
dependent on отображение
when in область
now or when in область
У каждого отображения в окне данных есть заголовок, содержащий его номер и отображаемое выражение (имя отображения). Под заголовком показывается значение отображения.
Вы можете выделить отображение, щелкнув на нем первой кнопкой мыши.
Можно расширить существующее выделение, нажав во время выбора клавишу Shift. Также можно переключить существующее выделение, удерживая клавишу Shift при выборе уже выделенных отображений.
Отдельные отображения можно также выделять, используя курсорные стрелки Up, Down, Left и Right.
Для выделения нескольких отображений нажмите и удерживайте первую кнопку мыши где-нибудь на заднем плане окна. При перемещении указателя показывается прямоугольник выделения; все отображения внутри этого прямоугольника будут выделены, когда вы отпустите кнопку мыши.
Если в процессе выделения нажата клавиша Shift, существующее выделение расширяется.
Двойной щелчок на заголовке отображения автоматически выделяет это отображение и все соединенные с ним.
Составные значения (например, записи, структуры, классы и массивы) могут отображаться в развернутом виде, то есть со всеми подробностями, или скрыто, в виде `{...}'.
Чтобы увидеть подробности составной величины, выберите эту величину, щелкнув на ее имени или значении первой кнопкой мыши и нажмите кнопку `Show'. Подробности показываются как для самой составной величины, так и для содержащихся в ней подструктур.
Чтобы скрыть подробности составной величины, выберите эту величину, щелкнув на ее имени или значении первой кнопкой мыши и нажмите кнопку `Hide'.
При нажатии и удержании первой кнопки мыши на кнопке `Show/Hide' всплывает меню с другими альтернативами:
Show More ()
Show Just ()
Show All ()
Hide ()
Есть более быстрый способ: вы можете также нажать на составной величине третью кнопку мыши и выбрать нужный пункт меню.
Еще более быстрый вариант: можно дважды щелкнуть на значении первой кнопкой мыши. Если какая-то часть значения скрыта, будет показано больше подробностей; если видимо все значение целиком, двойной щелчок скрывает значение. Таким способом вы можете дважды щелкать на значении до тех пор, пока не получите нужную степень подробности.
Если скрыты все подробности отображения, то такое отображение называется выключенным; на это указывает строка `(Disabled)'.
Отображения также можно включать и выключать с помощью команды DDD, вводимой в подсказке отладчика:
graph disable display отображения...
выключает заданные отображения.
graph enable display отображения...
включает заданные отображения.
В этих командах отображения... -- это либо разделенный пробелами список номеров отображений, либо имя одного отображения. Если вы задаете отображение по имени, затрагиваются все отображения с этим именем.
Для отмены включения или выключения отображений используйте `Edit => Undo'.
Массивы, структуры и списки могут быть ориентированы горизонтально или вертикально. Чтобы изменить ориентацию отображения, выделите его, а затем щелкните на кнопке `Rotate'.
Есть более быстрый способ: вы можете нажать на массиве третью кнопку мыши и выбрать из всплывающего меню пункт `Rotate'.
Если структура или список ориентированы горизонтально, DDD автоматически не показывает имена членов. Это может быть удобно для экономии места.
Последняя выбранная ориентация используется при создании новых отображений. Если в последний раз вы повернули массив горизонтально, следующий массив будет также ориентирован горизонтально. Эти установки сохраняются через `Edit => Save Options'; они связаны с такими ресурсами:
Вы можете отобразить все локальных переменные сразу, выбрав `Data => Display Local Variables'. При использовании DBX, XDB, JDB или Perl это отобразит все локальные переменные, включая аргументы текущей функции. При использовании GDB или PYDB аргументы содержатся в отдельном отображении, которое активизируется через `Data => Display Arguments'.
Отображением, показывающим локальные переменные, можно манипулировать точно так же, как любым другим. Отдельные переменные можно выделять и получать их значения.
Вы можете создать отображение из вывода произвольной команды отладчика. Если ввести
graph display `команда`
вывод команды превращается в отображение состояния, которое обновляется при каждом останове программы.
К примеру, команда
graph display `where`
создает отображение состояния с именем `Where', которое показывает текущий след вызовов.
Если вы используете GDB, DDD предоставляет панель, где вы можете выбрать полезные отображения состояния. Нажмите `Data => Status Displays' и подберите нужное отображение из списка.
Для обновления отображений состояния при каждом останове требуется некоторое время; их лучше удалять, когда они больше не нужны.
Окно данных автоматически обновляется при каждом останове программы. Значения, которые изменились с последнего обновления, подсвечиваются.
Однако, могут быть ситуации, когда вам нужно обновить окно данных вручную. Чаще всего такое случается, когда вы изменили установки отладчика, которые могут повлиять на формат данных, и хотите, чтобы в окне данных отразились эти установки.
Вы можете обновить окно данных, выбрав `Data => Refresh Displays'.
В качестве альтернативы, вы можете нажать третью кнопку мыши на фоне окна данных и выбрать пункт `Refresh Displays'.
Ввод
graph refresh
в подсказке отладчика приводит к тому же результату.
Если вы исследуете несколько переменных одновременно, выделение для каждой из них отдельного отображения займет много места на экране. Поэтому DDD поддерживает группы. Группа объединяет несколько логических отображений данных в одно физическое отображение, сберегая экранное место.
Есть два способа создания групп:
Отображения в группе можно выделять и манипулировать ими как частями обычного отображения; в частности, вы можете показывать и скрывать подробности или получать значения по указателям. Однако, нельзя проводить связки к группированному отображению, и вы можете выбирать либо только один из них, либо все сразу.
Выключение группы называется разгруппировкой, его тоже можно делать двумя способами:
Чтобы отобразить несколько последовательных объектов одного типа (часть массива или массив динамической длины), вы можете использовать в выражениях для отображения запись `от..до'.
от и до -- это числа, которые обозначают первое и последнее выражение из тех, что следует отобразить. Таким образом,
graph display argv[0..9]
создает 10 новых отображений для `argv[0]', `argv[1]', ..., `argv[9]'. Эти отображения автоматически группируются (см. раздел 7.3.1.8 Группировка отображений), так что вы можете легко обращаться с этим набором, как с массивом.
Запись `от..до' можно также применять несколько раз. Например,
graph display 1..5 * 1..5
создает удобную маленькую таблицу умножения.
Запись `от..до' создает несколько отображений; для их создания и обновления затрачивается некоторое время. Если вы хотите отобразить только часть массива, более эффективным будет использование фрагментов массива. См. раздел 7.3.2.1 Фрагменты массива, обсуждение этой темы.
Вы можете просмотреть состояние всех отображений, выбрав `Data => Displays'. Это вызывает редактор отображений.
Редактор отображений показывает свойства каждого отображения с такими полями:
Чтобы удалить одно отображение, выделите его и нажмите кнопку `Undisp'. Или вы можете нажать на этом отображении третью кнопку мыши и выбрать пункт меню `Undisplay'.
При удалении отображения автоматически выделяются его непосредственные потомки и предки, так что вы можете легко удалить целый граф.
Чтобы удалить несколько отображений за один раз, используйте кнопку `Undisp' в редакторе отображений (вызывается через `Data => Displays'). Выберите любое число отображений и удалите их, нажав `Undisp'.
Или вы можете применить такую команду DDD:
graph undisplay отображения...
В данном случае, отображения... -- это либо разделенный пробелами список номеров отображений, либо имя одного отображения. Если вы задаете отображение по имени, затрагиваются все отображения с этим именем.
Если вы используете объединенные окна, то при удалении последнего отображения из окна данных это окно автоматически закрывается. (Вы можете изменить это через `Edit => Preferences => Data => Close data window when deleting last display'.)
Если вы удалили отображение по ошибке, используйте `Edit => Undo', чтобы снова создать его.
Наконец, вы можете также вырезать, копировать и вставлять отображения с помощью пунктов `Cut', `Copy' и `Paste' из меню `Edit'. Буфер обмена хранит команды, используемые для создания отображений; `Paste' вставляет команду в консоль отладчика. Это позволяет вам сохранять отображения для будущего использования или копировать их между разными экземплярами DDD.
Вы можете использовать следующие ресурсы для управления внешним видом отображений:
В DDD есть специальные средства для обращения с массивами.
Часто бывает нужно напечатать несколько последовательных объектов одного типа; фрагмент (секцию) массива или массив динамически определяемой длины, для которого в программе существует только указатель.
В DDD вы можете отображать фрагменты с помощью записи `от..до' (см. раздел 7.3.1.9 Создание нескольких отображений). Но это подразумевает, что вы заранее знаете значения от и до; кроме того, создавать несколько одиночных отображений неэффективно. Если вы используете GDB, у вас есть другой способ.
При использовании GDB вы можете отображать последовательные объекты, ссылаясь на непрерывную область памяти как на искусственный массив с помощью бинарного оператора `@'. Левая часть `@' должна быть первым элементом желаемого массива и самостоятельным объектом. Правая часть -- это желаемая длина массива. Результатом является значение-массив, чьи элементы принадлежат типу первого аргумента. Первый элемент -- это на самом деле левый аргумент оператора; второй элемент состоит из байт памяти, непосредственно следующих после первого, и так далее.
Вот пример. Если в программе сказано
int *array = (int *) malloc (len * sizeof (int));
вы можете напечатать содержимое array
с помощью
print array[0]@len
и отобразить его, введя команду
graph display array[0]@len
Таким образом, общий вид отображения фрагмента массива такой:
graph display массив[первый]@число-элементов
где массив -- это имя отображаемого массива, первый -- это индекс первого элемента, а число-элементов -- это число отображаемых элементов.
Левый операнд `@' должен находиться в памяти. Значения-массивы, созданные таким методом при помощи оператора `@', ведут себя в отношении индексирования так же, как любые другие массивы, а при использовании в выражениях приводятся к типу указателей.
При использовании GDB значение массива, которое повторяется 10 и более раз, отображается только один раз. Это значение показывается с добавленным постфиксом `<nx>', где n -- это число повторений. Таким образом, отображение `0x0 <30x>' обозначает массив из 30 элементов, каждый из которых равен `0x0'. Это значительно экономит экранное место, особенно в случае с однообразными массивами.
По умолчанию порог для повторяющихся элементов массива равен 10. Вы
можете изменить эго через `Edit => GDB Settings =>
Threshold for repeated print elements'. Если установить порог в
значение 0
, GDB (и DDD) будут отображать все элементы
массива по отдельности. После изменения установок GDB не забывайте
обновить окно данных с помощью `Data => Refresh Displays'.
Вы также можете настроить DDD для раздельного отображения элементов массивов:
По умолчанию DDD располагает двумерные массивы в виде таблиц, так чтобы все элементы массива были выровнены относительно друг друга.(27) Чтобы выключить это средство, снимите установку `Edit => Preferences => Data => Display Two-Dimensional Arrays as Tables'. Она связана с таким ресурсом:
Во время работы программы вы можете изменять значения любых переменных.(28)
Чтобы изменить значение переменной, введите ее имя в `()' --- например, выбрав отображение или появление переменной в исходном тексте программы. Затем щелкните на кнопке `Set'. В появившемся диалоговом окне вы можете отредактировать значение переменной; щелчок на кнопке `OK' или `Apply' применяет ваше изменение и присваивает переменной новое значение.
Чтобы изменить отображаемое значение, вы также можете выбрать пункт `Set Value' из всплывающего меню.
Если вы сделали ошибку, можно применить `Edit => Undo' и снова присвоить переменной старое значение.
Помимо отображения простых значений, DDD может визуализировать зависимости между значениями -- в особенности указатели и другие ссылки, которые составляют сложные структуры данных.
Зависимые отображения создаются из существующего отображения. Зависимость обозначается связкой, ведущей от начального отображения к зависимому.
Чтобы создать зависимое отображение, выделите начальное отображение или его часть и введите в поле аргумента `():' зависимое выражение. Затем щелкните на кнопке `Display'.
Используя зависимые отображения, вы можете исследовать структуру, например, дерева, и расположить его в соответствии с вашим интуитивным пониманием дерева как структуры данных.
По умолчанию DDD не распознает разделяемые структуры данных (то есть объект, на который ссылаются несколько других объектов). См. раздел 7.3.4.3 Разделяемые структуры, для получения подробной информации о том, как исследовать такие структуры.
Есть специальные средства для создания зависимых отображений, показывающих значение, на которое ссылается указатель. Это позволяет быстро исследовать структуры данных, основанные на указателях.
Чтобы получить значение по указателю, выделите значение или имя начального указателя и щелкните на кнопке `Disp *'. Появится новое отображение, показывающее значение по этому указателю.
Более быстрый способ: вы можете нажать на значении или имени начального указателя третью кнопку мыши и выбрать пункт меню `Display *'.
Есть еще более быстрый вариант: дважды щелкните первой кнопкой мыши на значении или имени начального указателя. Есть во время двойного щелчка вы нажмете Ctrl, отображение будет заменено на значение, хранящееся по этому указателю.
Функция `Display *()' также доступна по нажатию и удержанию кнопки `Display'.
По умолчанию DDD не распознает разделяемые структуры данных -- то есть объект, на который ссылаются несколько других объектов. Например, если два указателя `p1' и `p2' ссылаются на один и тот же объект `d', отображения `d', `*p1' и `*p2' будут различными, хотя они и обозначают один и тот же объект.
DDD предоставляет специальный режим, в котором такие ситуации детектируются. DDD замечает, когда два или более отображения расположены по одному физическому адресу, и если это так, объединяет все эти псевдонимы в одно отображение, оригинальное отображение данных. Этот режим называется режимом детектирования псевдонимов; включается через `Data => Detect Aliases'.
Когда включено детектирование псевдонимов, DDD проверяет адреса всех отображений после каждого шага программы. Если два отображения имеют одинаковый адрес, они объединяются в одно. Точнее, остается только одно, которое не изменялось дольше (это оригинальное отображение данных); все остальные псевдонимы подавляются, то есть полностью скрываются. Ведущие к псевдонимам связки заменяются на связки, ведущие к оригинальному отображению.
При детектировании псевдонимов создаются особенные связки: вместо того, чтобы непосредственно соединять два отображения, они проходят через подсказку, которая описывает данную дугу.
В каждой подсказке связки есть место для скрытого псевдонима; выделение подсказки эквивалентно выделению этого псевдонима. Таким образом, вы можете легко удалять отображения-псевдонимы, просто выделяя подсказку и нажимая `Undisp'.
Для получения доступа к отображениям-псевдонимам, вы также можете использовать редкатор отображений. Скрытые отображения перечисляются в нем как псевдонимы оригинального отображения. С помощью редактора отображений можно выделять, изменять и удалять скрытые отображения.
Скрытые отображения снова становятся видимыми, как только вы выключаете детектирование псевдонимом, или если их адреса меняются так, что они больше не являются псевдонимами, или если удаляется оригинальное отображение, -- и тогда оригинальным отображением становится псевдоним, изменявшийся позднее других.
Пожалуйста, обратите внимание на следующие возможные проблемы, связанные с детектированием псевдонимов:
Детектирование псевдонимов управляется следующими ресурсами:
В DDD есть быстрое меню часто используемых выражений для работы с отображениями. Это меню активизируется нажатием и удержанием кнопки `Display', или нажатием на некотором отображении третьей кнопки мыши и выбором `New Display', или щелчком на отображении третьей кнопки мыши при нажатой клавише Shift.
Пункт быстрого меню `Other' позволяет создавать новое отображение, которое расширяет быстрое меню.
В качестве примера предположим, что вы выделили отображение с именем `date_ptr'. Если выбрать `Display => Other', появится диалоговое окно, позволяющее ввести новое отображаемое выражение -- к примеру, вы можете преобразовать отображение `date_ptr' в новое отображение `(char *)date_ptr'. Если был активизирован переключатель `Include in `New Display' Menu', быстрое меню теперь будет включать новый пункт `Display (char *)()', который преобразует любое выделенное отображение отображение в `(char *)отображение'. Такие быстрые операции могут сэкономить много времени при исследовании сложных структур данных.
Вы можете отредактировать содержимое меню `New Display', выбрав его пункт `Edit Menu'. Появится редактор быстрых операций, содержащий все быстрые выражения, которые вы можете отредактировать по своему усмотрению. Каждая строка содержит выражение для ровно одного пункта меню. Если щелкнуть на `Apply', в соответствии с этим текстом будет заново создано меню `New Display'. Если текст пуст, меню `New Display' тоже будет пустым.
DDD также позволяет задавать отдельные метки для определенных пользователем кнопок. Вы можете записать такую метку после выражения, отделив ее знаками `//'. Эта возможность используется по умолчанию в меню `New Display' для GDB, где у каждого преобразования есть своя метка:
/t () // Convert to Bin /d () // Convert to Dec /x () // Convert to Hex /o () // Convert to Oct
Если хотите, можете добавить свои преобразования. DDD поддерживает до двадцати пунктов в меню `New Display'.
Быстрое меню контролируется следующими ресурсами:
Если строка содержит разделитель метки(29), то строка до разделителя используется в качестве выражения, а строка после разделителя --- в качестве метки. Иначе, меткой будет `Display выражение'. При вызове строка `()' в выражении заменяется на имя текущего выделенного отображения.
Если у вас одновременно есть несколько отображений, вы можете организовать их по своему вкусу. В этом разделе рассказывается как это сделать.
Время от времени бывает нужно переместить отображение на другое место в окне данных. Вы можете переместить одно отображение, нажимая и удерживая на его заголовке первую кнопку мыши. Перемещая указатель при удержании кнопки, вы перемещаете все выделенные отображения.
Подсказки связок можно выделять и перемещать точно так же, как отображения. Если дуга проходит через подсказку связки, вы можете изменить форму этой дуги, передвигая подсказку.
Для точного перемещения выделенных отображений можно также воспользоваться курсорными стрелками. При нажатой клавише Shift курсорные стрелки перемещают по одному пикселю, а при нажатом Ctrl --- по узлам сетки.
Если окно данных становится слишком маленьким, и все отображения в нем не умещаются, создаются полоски прокрутки. Если DDD у вас настроен на использование панели прокрутки, то в нижнем правом углу создается панель прокрутки. Когда вы перемещаете панель прокрутки, соответственно перемещается видимая часть окна.
Чтобы перейти от полосок прокрутки к панели прокрутки, используйте `Edit => Startup => Data Scrolling' и выберите либо `Panner', либо `Scrollbars'.
Эта установка привязана к следующему ресурсу:
См. раздел 2.1.2 Ключи DDD, о ключах --scrolled-graph-editor
и
--panned-graph-editor
.
Вы можете выровнять все отображения по ближайшим узлам сетки, выбрав `Data => Align on Grid'. Это бывает полезно, если вы хотите, чтобы все связки были строго горизонтальны или вертикальны.
Если установить `Edit => Preferences => Data => Auto-align Displays on Nearest Grid Point', отображения выравниваются автоматически. Когда эта установка включена, отображения можно перемещать только по сетке.
Вы можете скомпоновать весь граф как дерево, выбрав `Data => Layout Graph'.
Компоновка графа может создать подсказки связок; то есть связки становятся не прямыми линиями, а ведут к подсказке, а от нее уже к месту назначения. Подсказки отображений можно перемещать так же, как любые отображения.
Чтобы включить более компактную компоновку, можно установить `Edit => Preferences => Data => Compact Layout'. Эта установка реализует альтернативный алгоритм компоновки, где потомки помещаются рядом со своими предками. Этот алгоритм подходит только для гомогенных структур.
Вы можете включить принудительную компоновку, выставив `Edit => Preferences => Data => Automatic Layout'. Если задействована автоматическая компоновка, граф компонуется после каждого изменения.
Вы можете повернуть весь граф на 90 градусов по часовой стрелке, выбрав `Data => Rotate Graph'.
Если граф ранее был скомпонован, может понадобиться перекомпоновать его. Последующие компоновки будут учитывать направление последнего поворота.
DDD позволяет распечатывать граф на PostScript-принтерах или в файлы. Это полезно для документирования состояний программы.
Чтобы напечатать граф на PostScript-принтере, выберите `File => Print Graph'. Введите в поле `Print Command' команду печати. Чтобы начать печать, нажмите кнопку `OK' или `Apply'.
Еще можно распечатать граф в файл. Щелкните на кнопке `File' и введите в поле `File Name' имя файла. Чтобы создать файл, щелкните на кнопке `Print'.
Когда граф печатается в файл, возможны два формата:
xfig
или для преобразования в другие форматы (в том
числе в @acronym{IBMGL}, TeX, @acronym{PIC}) с помощью программ
transfig
или fig2dev
.
Пожалуйста, обратите внимание на следующие возможные проблемы, связанные с печатью графов:
Эти установки связаны с такими ресурсами:
В этом разделе обсуждается, как DDD на самом деле создает отображения из данных.
Все данные, отображаемые в окне данных DDD, предоставляются подчиненным отладчиком. GDB, к примеру, предоставляет список отображений, содержащий символьные выражения, которые следует вычисляют т печатать на стандартный вывод при каждом останове программы. Команда GDB `display tree' добавляет к списку отображений `tree' и заставляет GDB печатать значение `tree', например, в виде `tree = (Tree *)0x20e98', при каждом останове программы. DDD обрабатывает этот вывод GDB и показывает его в окне данных.
Каждый элемент списка отображений, в том виде, в каком он передается от подчиненного отладчика, считывается в DDD и переводится в бокс. Боксы -- это такие прямоугольники с определенным содержимым, которые можно отображать в окне данных. Различают атомарные и составные боксы. Атомарный бокс содержит белый или черный пробел, линию или строку. Составные боксы -- это горизонтальные или вертикальные группы других боксов. Каждый бокс обладает размером и протяженностью, которые определяют его положение во внешнем пространстве.
Составляя все большие и большие боксы DDD создает из структуры данных GDB узел графа, подобно тому, как системы набора текстов вроде TeX строят из букв слова, а из абзацев страницы.
Такие конструкции легко выражаются посредством функций, задающих зависимость бокса от других боксов. Эти функции отображения могут задаваться пользователем, а потом интерпретироваться в DDD, с помощью функционального языка VSL, что означает visual structure language. Пользователь может сам задавать VSL-функции, это оставляет большие пространство для расширений и настроек. VSL-функция отображения, которая помещает вокруг своего аргумента рамку, выглядит так:
// Поместить рамку вокруг текста TEXT frame(text) = hrule() | vrule() & text & vrule() | hrule();
Здесь hrule()
и vrule()
-- это примитивы, возвращающие,
соответственно, горизонтальную и вертикальную линии. Операторы `&'
и `|' создают горизонтальное и вертикальное выравнивание своих
аргументов.
VSL предоставляет базовые средства, такие как сопоставление с
образцом и функции с переменным числом аргументов. Функция
halign()
, к примеру, строит горизонтальное выравнивание для
произвольного числа аргументов, которым соответствуют три точки
(`...'):
// Горизонтальное выравнивание halign(x) = x; halign(x, ...) = x & halign(...);
Часто используемые функции, вроде halign()
, собраны в стандартную
библиотеку VSL.
Чтобы визуализировать структуры данных, каждому атомарному типу и каждому типу-конструктору языка программирования присваивается VSL-функция отображения. Атомарные значения, такие как числа, знаки, перечисления или строки, отображаются с помощью строковых боксов, содержащих их значение; VSL-функция для их отображения оставляет их без изменений:
// Атомарные значения simple_value(value) = value;
Составные значения требуют большего внимания. Массив, к примеру, можно отобразить при помощи горизонтального выравнивания:
// Массив array(...) = frame(halign(...));
Когда GDB посылает DDD значение массива, вызывается VSL-функция `array()' с элементами этого массива в качестве значений. Таким образом, выражение-массив GDB `{1, 2, 3}' вычисляется в VSL как
array(simple_value("1"), simple_value("2"), simple_value("3"))
что эквивалентно
"1" & "2" & "3"
составному боксу, содержащему три горизонтально выровненных строковых бокса. VSL-функция, которая используется в DDD на самом деле, также помещает между элементами разделители, и у нее есть вертикальный вариант.
Вложенные структуры, вроде многомерных массивов, отображаются путем
последовательного применения функции array()
внизу вверх.
Сначала array()
применяется к наиболее глубоко вложенным
структурам; затем результирующие боксы передаются в качестве аргументов
в еще один вызов array()
. Вывод GDB
{{"A", "B", "C"}, {"D", "E", "F"}}
представляющий массив строк размером 2 на 3, вычисляется в VSL как
array(array("A", "B", "C"), array("A", "B", "C"))
результатом чего является выровненный горизонтальный бокс двух других боксов, представляющих внутренние массивы.
Структуры-записи строятся похожим способом, с использованием функции
отображения struct_member
,
для отрисовки членов записи. Имена и значения разделяются знаком
равенства:
// Член структуры-записи struct_member (name, value) = name & " = " & value;
Функция отображения struct
рисует саму запись с помощью функции
valign()
.(30)
// Структура-запись struct(...) = frame(valign(...));
Это простой пример; VSL-функция, которая на самом деле используется в DDD, еще пытается выровнять знаки равенства; кроме того, она гарантирует, что применяются разделители для правильного языка, что свернутые структуры отрисовываются правильно, и так далее.
С DDD поставляется встроенная библиотека VSL, которой должно быть достаточно для большинства, если не для всех, нужд. Используя следующие ресурсы можно изменять и улучшать определения VSL:
Общий шаблон для замены определения функции функция на новое определение нов_опр такой:
#pragma replace функция function(аргументы...) = нов_опр;
Часто используются такие VSL-функции:
color(бокс, цвет-текста [, цвет-фона])
display_color(бокс)
title_color(бокс)
disabled_color(бокс)
simple_color(бокс)
pointer_color(бокс)
struct_color(бокс)
array_color(бокс)
reference_color(бокс)
changed_color(бокс)
stdfontfamily()
stdfontsize()
0
(по умолчанию) говорит, что
следует применять `stdfontpoints()'.
stdfontpoints()
0
говорит, что следует
применять `stdfontsize()'. По умолчанию 90
.
stdfontweight()
Чтобы установить цвет указателей в значение "red4", напишите
Ddd*vslDefs: \ #pragma replace pointer_color\n\ pointer_color(box) = color(box, "red4");\n
Чтобы установить размер шрифта равным 10.0 пунктов, используйте
Ddd*vslDefs: \ #pragma replace stdfontsize\n\ #pragma replace stdfontpoints\n\ stdfontsize() = 0;\n stdfontpoints() = 100;\n
Чтобы по умолчанию использовался 12-пиксельный шрифт courier, напишите
Ddd*vslDefs: \ #pragma replace stdfontsize\n\ #pragma replace stdfontfamily\n\ stdfontsize() = 12;\n\ stdfontfamily() = family_courier();\n
Другие определения, которые вы можете перекрыть с помощью ресурса `vslDefs', смотрите в файле `ddd.vsl'.
Если дистрибутив исходников DDD у вас установлен в `/opt/src', вы можете использовать следующие установки, чтобы библиотека VSL считывалась из `/home/joe/ddd.vsl':
Ddd*vslLibrary: /home/joe/ddd.vsl Ddd*vslPath: .:/opt/src/ddd/ddd:/opt/src/ddd/vsllib
Включаемые VSL-файлы, на которые ссылается `/home/joe/ddd.vsl', сначала ищутся в текущем каталоге `.', потом в `/opt/src/ddd/ddd/', а потом в `/opt/src/ddd/vsllib/'.
Вместо того чтобы предоставлять еще одну библиотеку VSL, часто бывает проще задать какие-то незначительные изменения для встроенной библиотеки. Подробности смотрите выше, в описании ресурса `vslDefs'.
Если вам нужно исследовать огромный объем числовых данных, рисунок часто может сказать больше, чем тысяча чисел. Поэтому DDD позволяет вам рисовать числовые значения в виде двух- и трехмерных графиков.
DDD может строить графики двух типов числовых значений:
Чтобы построить график массива фиксированного размера, выделите его имя, щелкнув на нем первой кнопкой мыши. Имя массива будет скопировано в поле аргумента. Если щелкнуть на кнопке `Plot', в окне данных появится новое отображение, а потом будет создано новое окно верхнего уровня, содержащее график значений.
Для построения графика массива динамического размера вы должны использовать фрагмент массива (см. раздел 7.3.2.1 Фрагменты массива). Введите в поле аргумента
массив[первый]@число-элементов
где массив -- это имя отображаемого массива, первый -- это индекс первого элемента, а число-элементов -- это число отображаемых элементов. Затем щелкните на `Plot', чтобы начать построение графика.
Также вы можете получить график значений введя в подсказке отладчика такую команду:
graph plot выражение
Она работает подобно `graph display выражение' (и принимает такие же аргументы; см. раздел 7.3.1.1 Создание единичных отображений), но еще дополнительно показывает значение в окне графика.
Каждый раз, когда во время выполнения программы значение изменяется, график обновляется по текущим значениям. Окно графика остается активным до тех пор, пока вы не закроете его (через `File => Close'), или пока не будет удалено соответствующее ему отображение.
На самом деле DDD не сам строит график. Вместо этого он полагается
на внешнюю программу gnuplot
.
DDD добавляет к окну графика Gnuplot полоску меню, которая позволяет вам изменять внешний вид графика:
При просмотре трехмерного графика можно менять точку наблюдения с помощью полосок прокрутки. Горизонтальная полоска прокрутки поворачивает график вокруг оси z, то есть вправо или влево. Вертикальная полоска прокрутки поворачивает вокруг оси y, то есть вверх или вниз.
Вы также можете, если хотите, изменять размер окна графика.
Кроме графиков массивов, DDD может также строить графики скаляров (простых числовых величин). Делается это так же, как для массивов --- вы выбираете числовую переменную, щелкаете на `Plot', и появляется график. Однако, построение графика скаляра не так интересно. График, не содержащий ничего кроме скаляра, просто отображает значение этого скаляра в виде константы y -- то есть горизонтальную прямую.
Тогда зачем вообще беспокоиться о скалярах? DDD позволяет объединять на одном графике несколько значений. Основная идея такова: если вы хотите построить график чего-то, что не является ни массивом, ни скаляром, DDD берет из этого чего-то все числовые значения, какие может найти и чертит их графики в одном окне. Например, вы можете построить график всех локальных переменных, выбрав `Data => Display Local Variables' и нажав затем `Plot'. При этом создается график, содержащий все числовые переменные, найденные среди локальных переменных. Аналогично, вы можете получить график всех числовых членов какой-то структуры, выбрав ее и нажав `Plot'.
Если вы хотите точнее контролировать, что включать в график, а что нет, вы можете применить группы отображений (см. раздел 7.3.1.8 Группировка отображений). Довольно часто строят график одномерного массива вместе с текущим индексом. Это делается в три этапа:
Отображаемые вместе в массивами скаляры могут отрисовываться в виде либо горизонтальных, либо вертикальных линий. По умолчанию скаляры рисуются в виде горизонтальных линий. Однако, если скаляр является индексом ранее начерченного массива, он показывается как вертикальная линия. Вы можете изменить первоначальную ориентацию, выделив отображение скаляра и нажав `Rotate'.
При каждом останове программы DDD записывает значения всех отображаемых переменных, чтобы вы могли "отменить" выполнение программы (см. раздел 6.8 "Отмена" выполнения программы). Для таких историй отображений тоже можно построить график. Пункт меню `Plot => Plot history of ()' создает график, в котором показаны все записанные ранее значения выделенного отображения.
Если вы хотите распечатать график, выберите `File => Print Plot'. Появится диалог для печати графиков. Так же, как для графов, у вас есть выбор между печатью на принтере или в файл, и вы можете установить нужные параметры.
Собственно печать производит опять же Gnuplot, используя подходящий драйвер. Пожалуйста, обратите внимание на следующие возможные проблемы, связанные с печатью:
С помощью `File => Command' можно вводить команды Gnuplot напрямую. Каждая введенная в подсказку `gnuplot>' команда пересылается в Gnuplot, а после нее выдается команда `replot', которая обновляет изображение. Это полезно для выполнения в Gnuplot более сложных задач.
Вот простой пример. Команда Gnuplot
set xrange [xmin:xmax]
устанавливает диапазон отображения по горизонтали в значение xmin...xmax. Чтобы построить график только элементов от 10 до 20, введите:
gnuplot> set xrange [10:20]
После ввода каждой команды DDD добавляет команду replot
,
поэтому график обновляется автоматически.
А вот более сложный пример. Следующая последовательность команд Gnuplot сохраняет график в формате TeX:
gnuplot> set output "plot.tex" # Устанавливает имя выходного файла gnuplot> set term latex # Задает выходной формат gnuplot> set term x11 # Снова показывает первоначальное изображение
Из-за неявной команды replot
вывод автоматически записывается
в файл `plot.tex' после команды set term latex
.
Диалоговое окно запоминает введенные команды; чтобы восстановить ранее введенное, используйте курсорные стрелки. Сообщения об ошибках от Gnuplot (если они были), также показываются в области истории.
Диалог между DDD и Gnuplot сохраняется в файле
`~/.ddd/log' см. раздел 10.12.1 Запись протокола). Ключ DDD
--trace
печатает этот диалог на стандартный вывод.
Если вы хотите обработать данные графика с помощью какой-то внешней
программы (отдельной программой Gnuplot или программой xmgr
,
например), вы можете записать данные графика в файл, используя
`File => Save Data As'. При этом появится диалоговое окно,
позволяющее выбрать файл, в котором будут сохранены данные.
Генерируемый файл начинается несколькими строками комментариев. Затем идут сами данные в формате X/Y или X/Y/Z. Это тот же самый файл, какой обрабатывает Gnuplot.
Если вы хотите увидеть, как ваши данные меняются с течением времени, вы
можете создать точку останова, последовательность команд которой
завершается командой cont
(см. раздел 5.1.8 Команды точек останова).
Каждый раз, когда достигается эта точка останова "с продолжением",
DDD обновляет отображаемые значения, в том числе и графики. Затем
DDD выполняет последовательность команд точки останова, продолжая
выполнение.
Таким способом вы можете установить точку останова с "продолжением" в каком-то характерном месте внутри обрабатывающего массив алгоритма, и DDD будет отображать процесс графически. Когда ваша программа остановится на самом деле, вы можете применить `Undo' и `Redo', чтобы снова отобразить и исследовать предыдущие ее состояния. См. раздел 6.8 "Отмена" выполнения программы, для дополнительной информации.
Вы можете указать, как вызывается программа Gnuplot, и настроить некоторые базовые установки.
С помощью `Edit => Preferences => Helpers => Plot' вы можете указать, как вызывается программа Gnuplot. Это привязано к такому ресурсу:
С помощью `Edit => Preferences => Helpers => Plot Window' вы можете указать, следует ли использовать для графика окно Gnuplot (`External') или окно DDD (`builtin'). Это привязано к такому ресурсу:
mwm
, плохо справляются с
методами поглощения.
Можно и дальше управлять взаимодействием с внешним окном графика:
2000
.
Чтобы изменить установки Gnuplot, используйте такие ресурсы:
set parametric set urange [0:1] set vrange [0:1] set trange [0:1]
Установка `parametric' необходима, чтобы Gnuplot понимал генерируемые DDD файлы данных. Команды, задающие диапазоны, используются для построения графиков скаляров.
Дополнительные команды смотрите в документации по Gnuplot.
При использовании GDB или DBX вы можете просматривать содержимое памяти в нескольких форматах, независимо от типов данных вашей программы. Пункт меню `Data => Memory' выводит панель, где вы можете выбрать нужный формат.
В этой панели вы можете ввести
Есть два способа исследования значений:
Все кнопки, на которые вы щелкаете в DDD, в результате переводятся в команды отладчика; они показываются в консоли отладчика. Вы также можете набирать и редактировать эти команды непосредственно.
Вы можете общаться с командным интерфейсом подчиненного отладчика в консоли отладчика. Вводите команды в подсказке -- это `(gdb)' для GDB, `(dbx)' для DBX, `(ladebug)' для Ladebug, `>' для XDB, `>' и `нить[глубина]' для JDB, или `(Pydb)' для PYDB, или `DB<>' для Perl. Вы можете использовать любые команды отладчика; для ввода набирайте клавишу Return.
При использовании GDB или Perl вы можете завершать команды и аргументы, нажимая TAB. Это работает в консоли отладчика, а также во всех остальных текстовых окнах.
GDB может дополнить для вас остаток слова команды, если есть только один вариант; он также может в любое время показать допустимые варианты следующего слова команды. Это работает для команд GDB, подкоманд GDB и имен символов вашей программы.
Нажимайте клавишу TAB всякий раз, когда вы хотите, чтобы GDB дополнил остаток слова. Если есть только один вариант, GDB дополняет слово и ждет, пока вы завершите команду (или нажмете RET для ее ввода). Например, если вы наберете
(gdb) info bre TAB
GDB дополнит остаток слова `breakpoints', поскольку это
единственная подкоманда info
, начинающаяся на `bre':
(gdb) info breakpoints
Теперь вы можете либо нажать RET, чтобы запустить команду
info breakpoints
, либо нажать забой и ввести что-то еще, если
`breakpoints' -- это не та команда, которую вы собирались ввести.
(Если бы вы были точно уверены, что хотите info breakpoints
,
вы могли бы просто набрать RET сразу после `info bre',
применив возможность сокращения команд, а не дополнение.)
Если есть несколько вариантов следующего слова, то когда вы нажимаете TAB, DDD издает звуковой сигнал. Вы можете либо набрать больше знаков и попробовать снова, либо просто нажать TAB второй раз; GDB покажет все варианты завершения этого слова. Например, вы можете захотеть установить точку останова на подпрограмме, чье имя начинается на `make_', но когда вы набираете b make_TAB, DDD просто пищит. Если вы снова нажмете TAB, будут показаны имена всех функций из вашей программы, которые так начинаются. Если вы еще раз нажмете TAB, вы будете проходить по списку завершений, например:
(gdb) b make_ TAB DDD выдает сигнал; снова нажмите TAB и увидите вот это: make_a_section_from_file make_environ make_abs_section make_function_type make_blockvector make_pointer_type make_cleanup make_reference_type make_command make_symbol_completion_list (gdb) b make_ TAB DDD предоставляет одно дополнение за другим: (gdb) b make_a_section_from_file TAB (gdb) b make_abs_section TAB (gdb) b make_blockvector TAB
Показав возможные варианты, GDB копирует незавершенный ввод (в этом примере `b make_'), чтобы вы могли закончить команду -- повторно нажав TAB или введя остаток вручную.
Иногда вам нужна такая строка, которая хотя логически и является
"словом", но содержит скобки или другие знаки, которые GDB обычно
не включает в свое понятие слова. Чтобы завершение слов работало в
таких случаях, вы можете заключать слова в командах GDB в одиночные
кавычки ('
).
Наиболее вероятна ситуация, когда вам это понадобилось для набора имени
функции Си++. Это так, потому что Си++ допускает перезагрузку функций
(разные определения одной функции, отличающиеся типом аргумента).
Например, когда вы хотите поставить точку останова, вам может
понадобиться указать, имеете ли вы в виду версию name
,
принимающую параметр int
, name(int)
, или же версию,
принимающую параметр float
, name(float)
. Чтобы
использовать завершение слов в этой ситуации, наберите в начале имени
функции одиночную кавычку '
. Это предупреждает GDB о том, что
когда вы нажимаете TAB, чтобы запросить завершение слова, ему
следует принять во внимание больше информации, чем обычно:
(gdb) b 'bubble( TAB bubble(double,double) bubble(int,int) (gdb) b 'bubble(
В некоторых случаях DDD может понять, что для завершения имени требуется поставить кавычки. Когда это происходит, DDD вставляет кавычку за вас (завершая в то же время насколько может), если вы сначала не набрали ее:
(gdb) b bub TAB DDD изменяет введенную вами строку на показанную ниже и выдает звуковой сигнал: (gdb) b 'bubble(
Вообще, DDD может понять, когда нужна кавычка (и вставляет ее), если в момент запроса завершения перезагруженного символа вы еще не начали набирать список аргументов.
Если вы предпочитаете использовать клавишу TAB для переключения между объектами, снимите установку `Edit => Preferences => General => TAB Key completes in All Windows'. Это полезно в том случае, если фокус клавиатуры управляется указателем мыши (смотрите ниже), а у клавиши TAB нет особого назначения. Если эта установка включена, клавиша TAB завершает только в консоли отладчика.
Данная установка привязана к такому ресурсу:
Вы можете повторить предыдущие и последующие команды, нажимая стрелки Up и Down, соответственно. Это подставляет более ранние или более поздние команды в командную строку; чтобы применить текущую команду, нажмите Return.
Если вы введете пустую строку (просто нажмете Return в подсказке отладчика), будет повторена последняя команда.
`Commands => Command History' показывает историю команд.
Вы можете запустить поиск предыдущих команд, нажав Ctrl+B. Это вызывает режим наращиваемого поиска, где вы можете ввести строку, которую следует искать в предыдущих командах. Чтобы повторить поиск, нажмите Ctrl+B еще раз, а для поиска в обратном направлении используйте Ctrl+F. Чтобы вернуться в обычный режим, нажмите ESC или наберите любую команду управления курсором.
История команд автоматически сохраняется при выходе из DDD. Вы можете выключить эту возможность, установив следующий ресурс в значение `off':
Вместо того чтобы вводить команды с консоли отладчика, вы, возможно, предпочтете набирать их в окне терминала, из которого был вызван DDD.
Когда DDD вызывается с ключом --tty
, он включает
TTY-интерфейс, принимая команды отладчика со стандартного
ввода и пересылая вывод отладчика на стандартный вывод, как если бы
подчиненный отладчик был вызван непосредственно. В остальном все
функциональные возможности DDD остаются такими же.
По умолчанию, если DDD был вызван с ключом --tty
, консоль
отладчика закрыта. Чтобы открыть ее, используйте `View =>
Debugger Console'.
DDD можно настроить на использование библиотеки `readline' для
чтения команд со стандартного ввода. Эта библиотека GNU
предоставляет единый пользовательский интерфейс для программ,
управляемых из командной строки. Ее преимущества: редактирование команд
"на месте" в стиле GNU Emacs или vi
, подстановка из
истории, как в csh
, и сохраняемая между сеансами отладки
история команд. См. раздел `Command Line Editing' в Debugging with GDB, для
получения дополнительной информации о редактировании командой строки
через TTY-интерфейс.
Вы можете запускать DDD как подчиненный отладчик в других интерфейсах для отладчиков, комбинируя их возможности с возможностями DDD.
Чтобы запустить DDD в качестве подчиненного отладчика в другой
интерфейсной программе, нужно настроить ее так, чтобы вместо ее
подчиненного отладчика работал бы `ddd --tty'. Когда
DDD вызывается с ключом --tty
, он включает
TTY-интерфейс, принимая команды отладчика со стандартного
ввода и пересылая вывод отладчика на стандартный вывод, как если бы
подчиненный отладчик был вызван непосредственно. В остальном поведение
DDD не меняется.
В том случае, если ваш интерфейс отладчика использует ключ GDB
-fullname
, чтобы GDB сообщал позиции исходного кода,
--tty
задавать не обязательно. DDD распознает ключ
-fullname
, понимает, что его вызвали из другой интерфейсной
программы, и автоматически задействует TTY-интерфейс.
Если запустить DDD с ключом -fullname
, консоль отладчика и
окно исходного кода изначально выключены, так как предполагается, что их
предоставит внешний интерфейс. Если же нужно, вы можете зайти в меню
`View' и включить эти окна.
Чтобы интегрировать DDD с Emacs, наберите в Emacs M-x gdb или
M-x dbx, чтобы запустить сеанс отладки. В подсказке введите
ddd --tty
(и потом --dbx
или --gdb
,
если нужно) и имя отлаживаемой программы. Далее действуйте как обычно.
Чтобы интегрировать DDD с XEmacs, установите переменную
gdb-command-name
равной `"ddd"', вставив в свой файл
`~/.emacs' следующую строку:
(setq gdb-command-name "ddd")
Кроме того, можно вычислить это выражение, нажав ESC : и введя его непосредственно (ESC ESC в XEmacs 19.13 и более ранних).
Чтобы запустить из XEmacs сеанс отладки DDD, используйте `M-x gdb' или `M-x gdbsrc'. Далее работайте как обычно.
Чтобы интегрировать DDD с @acronym{XXGDB}, вызовите xxgdb
так:
xxgdb -db_name ddd -db_prompt '(gdb) '
Для упрощения взаимодействия с DDD вы можете добавлять свои собственные командные кнопки. Можно добавлять кнопки внизу консоли отладчика (`Кнопки консоли'), окна исходного кода (`Кнопки исходника') или окна данных (`Кнопки данных').
Для определения отдельных кнопок служит редактор кнопок, вызываемый через `Commands => Edit Buttons'. Редактор кнопок показывает текст, где каждая строка содержит команду для одной кнопки. Щелчок на `OK' создает соответствующие этому тексту кнопки. Если текст пуст (по умолчанию), кнопки не создаются.
В качестве простого примера, предположим, что вы хотите создать кнопку `print i'. Вызовите `Commands => Edit Buttons' и введите в редакторе кнопок строку `print i'. Затем щелкните на `OK'. Тогда внизу консоли отладчика появится кнопка с именем `Print i' -- попробуйте применить ее! Чтобы удалить эту кнопку, снова откройте редактор кнопок, очистите строку `print i' и нажмите `OK'.
Если команда кнопки содержит `()', строка `()' будет автоматически заменяться на содержимое поля аргумента. К примеру, кнопка с именем `return ()' будет выполнять команду GDB `return', передавая ей текущее содержимое поля аргумента.
По умолчанию DDD выключает все кнопки, чьи команду не поддерживаются подчиненным отладчиком. Чтобы задействовать их, снимите переключатель `Enable supported buttons only' в редакторе кнопок.
Кроме того, DDD позволяет задавать для определяемых пользователем кнопок управляющие последовательности и метки. См. раздел 10.4.1 Настройка кнопок, для получения подробностей.
DDD позволяет определять дополнительные командные кнопки; См. раздел 10.4 Определение кнопок. Данный раздел описывает ресурсы, контролирующие определяемые пользователем кнопки.
Следующие знаки имеют специальное значение:
...
, вставляют в консоль отладчика
свое имя и пробел.
Следующие имена кнопок зарезервированы:
По умолчанию значение этого ресурса пусто -- кнопки на консоли не создаются.
Вот несколько примеров, которые можно вставить в файл `~/.ddd/init'. Это установки DDD 1.x:
Ddd*consoleButtons: Yes\nNo\nbreak^C
Эта установка создает еще несколько кнопок:
Ddd*consoleButtons: \ Yes\nNo\nrun\nClear\nPrev\nNext\nApply\nbreak^C
Также смотрите ресурсы `dataButtons', `sourceButtons' и `toolButtons'.
По умолчанию значение этого ресурса пусто -- кнопки в окне данных не создаются.
По умолчанию значение этого ресурса пусто -- кнопки в окне исходного кода не создаются.
Вот несколько примеров, которые можно вставить в файл `~/.ddd/init'. Это установки DDD 1.x
Ddd*sourceButtons: \ run\nstep\nnext\nstepi\nnexti\ncont\n\ finish\nkill\nup\ndown\n\ Back\nForward\nEdit\ninterrupt^C
Эта установка создает несколько кнопок, которых нет в панели команд:
Ddd*sourceButtons: \ print *()\ngraph display *()\nprint /x ()\n\ whatis ()\nptype ()\nwatch ()\nuntil\nshell
Более профессиональная установка использует настраиваемые метки кнопок.
Ddd*sourceButtons: \ print *(()) // Print *()\n\ graph display *(()) // Display *()\n\ print /x ()\n\ whatis () // What is ()\n\ ptype ()\n\ watch ()\n\ until\n\ shell
Смотрите также ресурсы `consoleButtons' и `dataButtons' выше и ресурс `toolButtons' ниже.
По умолчанию значение этого ресурса равно
Ddd*toolButtons: \ run\nbreak^C\nstep\nstepi\nnext\nnexti\n\ until\nfinish\ncont\n\kill\n\ up\ndown\nBack\nForward\nEdit\nMake
Для каждой кнопки нужно указать положение на панели команд, используя ресурсы `XmForm'. Инструкции смотрите в файле ресурсов по умолчанию `Ddd'.
Если значение ресурса `toolButtons' пусто, панель команд не создается.
Следующие ресурсы определяют кнопки более подробно:
Кроме команд для точек останова (см. раздел 5.1.8 Команды точек останова), DDD также позволяет вам определять свои команды. Определяемая пользователем команда -- это последовательность команд, которой вы присвоили собственное имя как отдельной команде. Эту новую команду можно вводить в подсказке отладчика или вызывать по кнопке.
Кроме команд для точек останова (см. раздел 5.1.8 Команды точек останова), DDD также позволяет вам записывать последовательности команд в качестве новой, определенной пользователем команды GDB. Определяемая пользователем команда -- это последовательность команд GDB, которой вы придали новое имя как команде. В DDD для этой цели служит редактор команд, который вызывается через `Commands => Define Command'.
Команда GDB создается в пять шагов:
Когда команда определена, вы можете вводить ее в подсказке GDB. Кроме того, любую определенную пользователем команду можно применить, щелкнув на `Apply'.
Для удобства работы вы можете назначить для новой команды кнопку. Если включить одно из положений `Button', в указанном месте добавится кнопка с этой командой. Если вы хотите отредактировать эту кнопку, выберите `Commands => Edit Buttons'. См. раздел 10.4 Определение кнопок, обсуждение этой темы.
Когда выполняются определенные пользователем команды GDB, команды, составляющие ее определение, не печатаются. Ошибка в любой из команд последовательности приводит к останову выполнения.(33)
Команды, которые обычно запрашивают подтверждение, не задают вопросов при интерактивном использовании, если они находятся внутри определенной пользователем команды. Многие команды GDB, которые обычно печатают сообщения о том, что они делают в данный момент, не выводят этих сообщений при использовании из определенной пользователем команды.
Чтобы сохранить все определения команд, используйте `Edit => Save Options'.
Если вы хотите передать определяемой пользователем команде аргументы, вы можете включить переключатель `()' в редакторе команд. Это приводит к двум результатам:
В процессе определения команды вы можете как угодно переключать кнопку `()', переходя от символьной подстановки поля аргумента к буквальной.
В качестве примера давайте определим команду contuntil
, она
будет устанавливать точку останова по заданному аргументу и продолжать
выполнение.
У команд с аргументами есть маленький недостаток: у определяемой пользователем команды GDB нет никакой возможности получить доступ ко всему списку аргументов целиком; обрабатывается только первый аргумент (до пропуска). В будущих выпусках GDB это может измениться.
Если ваш подчиненный отладчик позволяет определять свои собственные последовательности команд, вы также можете использовать эти пользовательские команды из DDD; просто вводите их в подсказке отладчика.
Однако, вы можете столкнуться с некоторыми проблемами:
Для решения этих проблем DDD предоставляет простое средство, так называемые автокоманды. Если DDD получает от подчиненного отладчика какой-либо вывод вида `префикс команда', он интерпретирует команду, как если бы она была введена в подсказке отладчика. Префикс -- это определяемая пользователем строка, например `ddd: '.
Допустим, вы хотите определить команду gd
, которая служит
сокращением для graph display
. Все, что должна сделать
команда gd
-- выдать строку
ddd: graph display аргумент
где аргумент -- это аргумент gd
. При использовании
GDB этого можно достичь с помощью команды echo
. Вставьте в
свой файл `~/.gdbinit' такие строки:
define gd echo ddd: graph display $arg0\n end
Чтобы закончить подготовку, вы должны также установить ресурс `autoCommandPrefix' в значение префикса, который вы написали в команде, `ddd: '. Напишите в файле `~/.ddd/init':
Ddd*autoCommandPrefix: ddd:\
(Не забудьте поставить после обратной косой черты пробел.)
Теперь ввод gd foo
в подсказке отладчика будет иметь тот же
эффект, что и graph display foo
.
Пожалуйста, обратите внимание: Для своих команд вам лучше выбрать какой-нибудь другой префикс, не `ddd: '. Это нужно делать, потому что автокоманды создают проблему с защитой, ведь выполнять можно любые команды. Только представьте себе, что некая злобная программа пишет во время отладки строку вроде `префикс shell rm -fr ~'! Поэтому обязательно придумайте свой собственный префикс; его длина должна быть не меньше трех знаков.
Иногда желательно исследовать программу не только на уровне исходного текста, но и на уровне машинного кода. DDD предоставляет для этой задачи специальные окна машинного кода и регистров.
Чтобы включить поддержку отладки на уровне машинного кода, выберите `Source => Display Machine Code'. Когда она включена, появляется дополнительное окно машинного кода, которое показывает код текущей функции.(31) Перемещая квадратик в правой части разделяющей линии между окном исходника и машинного кода, вы можете изменять размер этих окон.
Окно машинного кода работает во многом похоже на окно исходника. Вы можете устанавливать, сбрасывать или изменять точки останова, выбирая адрес и нажимая кнопки `Break' или `Clear'; также доступны обычные всплывающие меню. Точки останова и текущая выполняемая позиция отображаются одновременно и в окне исходного кода, и в окне машинного кода.
Кнопку `Lookup' можно применять для поиска машинного кода конкретной функции или функции по конкретному адресу. Просто щелкните на нужной позиции в одном окне и нажмите `Lookup', и увидите соответствующий код в другом окне.
Если исходный код недоступен, обновляется только окно машинного кода.
Вы можете настраивать различные аспекты окна дизассемблированного вывода. См. раздел 8.4 Настройка окна машинного кода, для получения подробностей.
Все средства, доступные в окне исходного кода, также доступны в окне машинного кода. Для отладки на уровне машинного кода удобны две особые возможности:
Чтобы выполнить ровно одну машинную инструкцию, щелкните на кнопке `Stepi' или выберите `Program => Step Instruction'.
Чтобы продолжить до следующей инструкции в текущей функции, щелкните на кнопке `Nexti' или выберите `Program => Next Instruction'. Это похоже на `Stepi', но все вызовы подпрограмм выполняются без остановки.
При использовании GDB часто бывает полезно делать
graph display /i $pc
во время пошагового выполнения машинных инструкций. Это велит DDD автоматически показывать, какая инструкция будет выполнена следующей, всякий раз, когда программа останавливается.
DDD предоставляет окно регистров, в котором после каждого останова программы показываются значения машинных регистров. Чтобы включить это окно, выберите `Status => Registers'.(32)
Если выбрать один из регистров, его имя скопируется в поле аргумента. Вы можете использовать его, например, в качестве значения для `Display', чтобы получить отображение его значения в окне данных.
Включение машинного кода через `Source => Display Machine Code' (см. раздел 8.1 Исследование машинного кода) переключает следующий ресурс:
--disassemble
и --no-disassemble
.
Вы можете оставить дизассемблированный код в памяти, используя `Edit => Preferences => Source => Cache Machine Code':
Вы можете изменять ширину отступа для машинного кода, используя `Edit => Preferences => Source => Machine Code Indentation':
4
.
Ресурс `maxDisassemble' говорит, какой объем кода нужно дизассемблировать. Если `maxDisassemble' равен 256 (по умолчанию), а текущая функция больше 256-ти байт, DDD дизассемблирует только первые 256 байт от текущей позиции. Вы можете установить ресурс `maxDisassemble' в большее значение, если предпочитаете более обширный обзор машинного кода.
256
).
Если значение этого ресурса равно нулю, текущая функция дизассемблируется
полностью.
Вы можете запустить отлаживаемую программу, возможно, с аргументами, в любой среде по вашему выбору. Вы можете перенаправлять ввод и вывод программы, отлаживать уже работающий процесс или уничтожить процесс-потомок.
Чтобы запустить выполнение отлаживаемой программы, выберите `Program => Run'. У вас спросят, какие аргументы нужно передать программе. Можно либо выбрать из списка ранее использовавшиеся аргументы, либо ввести новые в текстовом поле. Потом нажмите кнопку `Run', и начнется выполнение программы с указанными аргументами.
Чтобы повторно запустить программу с теми же аргументами, выберите
`Program => Run Again' или нажмите кнопку `Run' на
панели команд. Или можно ввести run
и затем аргументы в
подсказке отладчика.
При щелчке на `Run' программа сразу начинает выполняться. См. раздел 5. Останов программы, обсуждение того, как подготовить останов программы. Как только программа остановилась, вы можете вызывать ее функции для исследования данных. См. раздел 7. Исследование данных, для получения подробностей.
Если время изменения файла символов изменилось с последнего раза, когда GDB считывал его, GDB сбрасывает таблицу символов и считывает ее снова. При этом GDB и DDD стараются сохранить текущее состояние отладчика, в частности, точки останова.
Аргументы программы задаются аргументами команды `run', они указываются через `Program => Run'.
В GDB, эти аргументами передаются оболочке, которая раскрывает знаки
подстановки и производит перенаправление ввода/вывода, а от оболочки ---
вашей программе. Переменная среды SHELL
(если такая есть)
указывает, какую оболочку использует GDB. Если вы не определяете
SHELL
, GDB использует `/bin/sh'.
Если вы пользуетесь другим подчиненным отладчиком, точная семантика интерпретации аргументов зависит от вашего подчиненного отладчика. Как правило для передачи аргументов применяется оболочка, чтобы вы могли использовать при описании аргументов обычные соглашения (такие как раскрытие символов подстановки или переменные).
Обычно ваша программа наследует среду от подчиненного отладчика, который наследует среду от DDD, а он в свою очередь -- от процесса-предка (обычно это оболочка).
В GDB, вы можете изменять те части среды, которые затрагивают вашу
программу, используя команды set environment
и unset
environment
. См. раздел `Your Program's Environment' в Debugging with GDB, для дополнительной информации.
DDD устанавливает следующие переменные среды:
DDD
DDD
, отлаживаемая программа (или подчиненный отладчик) может
узнать, что ее вызвал DDD.
TERM
TERMCAP
PAGER
Подчиненный отладчик, в свою очередь, может устанавливать или снимать некоторые переменные среды.
Программа обычно наследует рабочий каталог от подчиненного отладчика, который наследует его от DDD, а он в свою очередь -- от ПРОЦЕССА-предка (обычно это оболочка).
Вы можете изменить рабочий каталог подчиненного отладчика через `File => Change Directory' или с помощью его команды `cd'.
По умолчанию отлаживаемая программа производит ввод и вывод в консоли отладчика. Обычно вы можете перенаправить ввод и/или вывод вашей программы с помощью средств перенаправления оболочки с аргументами --- то есть задавая дополнительные аргументы вида `< ввод' или `> вывод'. Такие перенаправления можно писать точно так же, как и остальные аргументы (см. раздел 6.1.1 Аргументы программы).
Внимание: Хотя перенаправление ввода и вывода работают, вы не можете использовать конвейры для передачи вывода отлаживаемой программы другой программе; если вы попытаетесь это сделать, DDD может начать отлаживать не ту программу. См. раздел 6.3 Подсоединение к процессу, описание альтернативного способа.
Если вывод команд посылается на консоль отладчика, DDD не может отличить вывод отлаживаемой программы от вывода подчиненного отладчика.
Определенные виды вывода программ могут смущать DDD, сюда входят:
Если ваша программа выводит любые из этих строк, вы можете столкнуться с проблемами, когда DDD ошибочно принимает их за вывод отладчика. Эти проблемы можно легко обойти, перенаправив ввод/вывод программы, например, в отдельное окно выполнения (см. раздел 6.2 Использование окна выполнения).
Если подчиненный отладчик изменяет принимаемые по умолчанию установки
терминала, например, через команду stty
в файле инициализации,
DDD также может сбиться. То же относится к случаю, когда установки
терминала изменяет отлаживаемая программа.
Поведением консоли отладчика можно управлять с помощью следующего ресурса:
По умолчанию ввод и вывод вашей программы передаются на консоль отладчика. В качестве альтернативы DDD также может вызвать окно выполнения, где показывается терминальный ввод и вывод программы.(21)
Чтобы активизировать окно выполнения, выберите `Program => Run in Execution Window'.
Окно выполнения открывается автоматически, как только вы запускаете отлаживаемую программу. Пока оно активно, DDD перенаправляет в него стандартный ввод, вывод и протокол ошибок вашей программы. Заметьте, что устройство `/dev/tty' по-прежнему ссылается на консоль отладчика, не на окно выполнения.
Вы можете перекрыть установки потоков DDD, задавая в качестве аргументов альтернативные операции перенаправления. Например, чтобы программа читала из файла, но писала в окно выполнения, вызовите ее с аргументом `< файл'. Аналогично, чтобы перенаправить стандартный протокол ошибок на консоль отладчика, используйте `2> /dev/tty' (предполагается, что подчиненный отладчик и/или ваша оболочка UNIX поддерживают перенаправление стандартного протокола ошибок).
Вы можете настраивать окно выполнения DDD и использовать различные терминальные программы. Команда устанавливается через `Edit => Preferences => Helpers => Execution Window':
Ddd*termCommand: xterm -fn @FONT@ -e /bin/sh -c
Можно также установить тип терминала:
TERM
, которое следует передать
отлаживаемой программе. По умолчанию `xterm'.
Следующий ресурс говорит о том, активно окно выполнения или нет, как указано в `Program => Run in Execution Window'.
Если отлаживаемая программа уже работает в каком-то процессе, вы можете подсоединиться к этому процессу (вместо запуска нового с помощью `Run').(22)
Чтобы подсоединить DDD к процессу, выберите `File => Attach to Process'. Теперь вы можете выбрать процесс из списка. Выбрав, нажмите кнопку `Attach'.
После подготовки к отладке указанного процесса DDD первым делом останавливает его. Вы можете исследовать и изменять подсоединенный процесс, используя все команды DDD, которые обычно доступны, когда вы запустили процесс с помощью `Run'. Вы можете вставлять точки останова; пошагово проходить программу и продолжать ее выполнение; можете изменять память. Если вы сочли, что лучше оставить процесс работающим, вы можете использовать после подсоединения `Continue'.
При использовании `Attach to Process' вам нужно сначала указать, что за программа выполняется в процессе, с помощью `Open Program' и загрузить ее таблицу символов.
Закончив отладку подсоединенного процесса, вы можете освободить его от контроля DDD, используя `File => Detach Process'. При отсоединении процесс продолжает работу. После `Detach Process' этот процесс и DDD снова становятся совершенно не зависящими друг от друга, а вы можете подсоединиться к другому процессу или запустить новый с помощью `Run'.
Вы можете настраивать вид, в котором вам показывается список процессов, определяя другие команды для перечисления процессов. Смотрите `Edit => Preferences => Helpers => List Processes'; См. раздел 6.3.1 Настройка подсоединения к процессу, для получения подробностей.
При подсоединении к процессу (см. раздел 6.3 Подсоединение к процессу), DDD
использует для получения списка процессов команду ps
. Эта
команда определяется ресурсом `psCommand'.
ps
. В
зависимости от вашей системы, полезные альтернативы включают ps
-ef
и ps ux
. Первая строка вывода должна содержать заголовок
`PID', либо каждая строка должна начинаться с ID процесса.
Заметьте, что DDD фильтрует вывод этой команды; процесс показывается, только если к нему можно подсоединиться. Процесс самого DDD, а также процесс подчиненного отладчика также опускаются.
После того как программа запущена, она работает, пока не произойдет одно из следующих событий:
DDD показывает текущее состояние программы в консоли отладчика. Текущая выполняемая позиция отмечается стрелкой.
Если установлено `Edit => Preferences => General => Uniconify When Ready', DDD автоматически разворачивает себя, когда программа останавливается. Таким образом вы можете свернуть DDD на время длительных вычислений, и он сам развернется, когда программа остановится.
Чтобы возобновить выполнение в текущей позиции, щелкните на кнопке `Continue'. Все точки останова в текущей выполняемой позиции пропускаются.
Чтобы выполнить ровно одну строку исходного кода, щелкните на кнопке `Step'. Программа будет выполняться до тех пор, пока не достигнет другой исходной строки, которая может оказаться в другой функции. Потом программа останавливается, а управление возвращается DDD.
Внимание: Если вы используете кнопку `Step', когда управление принадлежит функции, которая была скомпилирована без отладочной информации, выполнение продолжается до тех пор, пока управление не достигнет функции, имеющей отладочную информацию. Аналогично, управление не будет заходить в функции без отладочной информации. Чтобы пошагово пройти такие функции, используйте кнопку `Stepi' (см. раздел 8.2 Выполнение машинного кода).
В GDB кнопка `Step' останавливается только на первой инструкции
исходной строки. Это предотвращает повторные остановы, которые раньше
случались в выражениях switch
, циклах for
и так далее.
`Step' продолжает до останова, если в пределах строки вызвана
функция с отладочной информацией.
Кроме того, `Step' в GDB входит в подпрограмму только в том случае, если для нее есть информация о номерах строк. Иначе эта кнопка действует как `Next'.
Чтобы продолжить до следующей строки в текущей функции, щелкните на кнопке `Next'. Это похоже на `Step', но все вызовы функций, появившиеся внутри текущей строки кода, выполняются без останова.
Выполнение останавливается, когда управление достигает другой строки кода в первоначальном уровне стека, в том, который выполнялся, когда вы нажали `Next'.
Чтобы продолжить выполнение до тех пор, пока не будет достигнута некая позиция, используйте средство `Continue Until Here' из всплывающего меню для строки. См. раздел 5.1.4 Временные точки останова, обсуждение этой темы.
Чтобы продолжить до тех пор, пока не будет достигнута строка, расположенная дальше текущей, щелкните на кнопке `Until'. Это полезно в тех случаях, когда нежелательно пошагово проходить цикл более одного раза.
`Until' похожа на `Next', только когда `Until' встречает переход, она автоматически продолжает выполнение, пока счетчик инструкций не станет больше адреса этого перехода.
Это означает, что когда вы достигаете конца цикла после его пошагового прохода, `until' делает так, что программа продолжает выполняться до выхода из этого цикла. Напротив, щелчок на `Next' в конце цикла просто переносит на его начало, и вы вынуждены пошагово проходить следующую итерацию.
`Until' всегда останавливает вашу программу, если она пытается покинуть текущий фрейм стека.
`Until' работает посредством пошагового выполнения инструкций, и следовательно, работает медленнее, чем продолжение до точки останова.
Чтобы продолжить выполнение до тех пор, пока текущая функция не вернется, используйте кнопку `Finish'. Возвращенное значение (если оно есть) будет напечатано.
Обычно, когда вы продолжаете выполнение программы, вы делаете это из того места, где она остановилась. Вместо этого вы можете продолжить с другого адреса по вашему выбору.
Чаще всего эта возможность применяется для возврата к старому состоянию --- вероятно, после установки новых точек останова в какой-то уже выполнившейся части программы, с целью более детального изучения ее работы.
Чтобы установить выполняемую позицию в текущей точке, используйте `Set Execution Position' из всплывающего меню точки останова. Этот пункт также доступен по нажатию и удержанию кнопки `Break/Clear'.(23)
В качестве более быстрой альтернативы, вы также можете нажать на стрелке первую кнопку мыши и перенести ее в другую позицию.(24)
Перемещение выполняемой позиции не изменяет ни текущий фрейм стека, ни указатель стека, ни содержимое какой-либо ячейки памяти, ни какие-либо регистры, кроме счетчика инструкций.
Некоторые подчиненные отладчики (в частности GDB) позволяют устанавливать новую выполняемую позицию в другой функции, не в текущей. Это может привести к странным результатам, если две эти функции получают разные наборы аргументов или локальных переменных. По этой причине при перемещении выполняемой позиции запрашивается подтверждение, если указанная строка не входит в текущую функцию.
После переноса выполняемой позиции щелкните на `Continue', чтобы продолжить выполнение.
Когда ваша программа остановилась, первое, что вам нужно знать, -- это где она остановилась, и как она там оказалась.
При каждом вызове функции, генерируется информация об этом вызове. Сюда включаются позиция вызова в программе, его аргументы и локальные переменные вызываемой функции. Эта информация сохраняется в блоке данных, называемом фреймом стека. Фреймы стека размещаются в области памяти, называемой стеком вызовов.
Когда программа останавливается, команды DDD для исследования стека позволяют вам увидеть всю эту информацию.
Один из фреймов стека является выбранным, и многие команды DDD неявно ссылаются именно на выбранный фрейм. В частности, всякий раз, когда вы запрашиваете у DDD значение некоторой переменной из вашей программы, это значение находится в текущем фрейме. Есть специальные команды DDD для выбора интересующего вас фрейма.
Стек вызовов разделяется на непрерывные фрагменты, называемые фреймами стека, или просто фреймами, для краткости; каждый фрейм представляет собой данные об одном вызове одной функции. Фрейм содержит переданные этой функции аргументы, ее локальные переменные и адрес, на котором она выполняется.
Когда программа начинает выполняться, стек содержит только один фрейм,
фрейм функции main
. Он называется начальным или
внешним фреймом. При каждом вызове функции создается новый фрейм.
При каждом возврате функции ее фрейм удаляется. Если функция
рекурсивная, у нее может быть несколько фреймов. Фрейм функции, в
которой на самом деле производятся вычисления, называется самым
внутренним фреймом. Это последний созданный фрейм, который еще
существует.
Внутри программы фреймы стека идентифицируются по адресам. Фрейм стека состоит из многих байт, у каждого свой адрес; для каждого типа компьютеров существует соглашение, по которому выбирается один байт, служащий адресом всего фрейма. Обычно, пока выполнение имеет место в каком-то фрейме, его адрес хранится в регистре, называемом регистр указателя фрейма.
GDB присваивает всем существующим фреймам стека номера, начиная с нуля для самого внутреннего, единицы для фрейма, вызвавшего нулевой, и так далее наверх. Эти номера на самом деле не существуют в вашей программе; GDB присваивает их, чтобы у вас была возможность адресации фреймов стека в командах GDB.
DDD предоставляет окно следа вызовов, дающее обзор пути, по которому прошла программа. В нем показывается одна строка на каждый фрейм, начиная от текущего (нулевого), далее следует фрейм, вызвавший текущий (первый), и так до вершины стека.
Чтобы включить окно следа вызовов, выберите `Status => Backtrace'.
При использовании GDB каждая строка следа вызовов показывает номер фрейма и имя его функции. Также показывается значение счетчика инструкций -- если только вы не применили команду GDB `set print address off'. Кроме того, выводятся имя исходного файла и номер строки, а также аргументы функции. Значение счетчика инструкций опускается, если оно находится в начале кода для этого номера строки.
Большинство команд для исследования стека и других данных программы действуют на фрейм, который выбран в данный момент. Вот команды для выбора фрейма стека.(25)
В окне следа вызовов вы можете выбирать произвольный фрейм, чтобы перемещаться от одного фрейма к другому. Просто щелкните на нужном фрейме.
Кнопка `Up' выбирает функцию, которая вызвала текущую -- то есть перемещает на один фрейм вверх.
Кнопка `Down' выбирает функцию, которая была вызвана из текущей --- то есть перемещает на один фрейм вниз.
Вы также можете непосредственно напечатать команды up
и
down
в подсказке отладчика. Ctrl+Up и Ctrl+Down,
соответственно, также перемещают по стеку.
Операции `Up' и `Down' можно отменить через `Edit => Undo'.
Если вы взглянете на пункт меню `Edit => Undo' после команды выполнения, вы обнаружите, что DDD предоставляет возможность отменять команды выполнения, так же, как любые другие команды. Значит ли это, что DDD позволяет перемещаться назад во времени, отменяя и выполнение программы, и все ее побочные эффекты?
К сожалению, должны вас разочаровать. DDD не может отменить то, что сделала ваша программа. (После недолгого размышления вы поймете, что это невозможно в общем случае.) Однако, DDD может сделать кое-что другое: он может показать ранее записанные состояния вашей программы.
После "отмены" команды выполнения (через `Edit => Undo' или кнопку `Undo'), позиция выполнения возвращается на старое место, а отображаемые переменные принимают более ранние значения. Состояние программы в действительности не меняется, но DDD показывает записанный вид более раннего состояния.
В этом, так называемом историческом режиме, большинство обычных команд DDD, которые запрашивают у программы информацию, выключаются, поскольку у отладчика нельзя получать сведения о предыдущем состоянии. Однако, вы можете исследовать текущую выполняемую позицию или отображаемые переменные. Используя `Undo' и `Redo' вы можете перемещаться назад и вперед во времени, чтобы понять, как программа достигла текущего состояния.
Чтобы вы знали, что действует исторический режим, стрелка выполнения (которая показывает прошлую позицию выполнения) и отображения переменных рисуются штриховыми линиями. Более того, в строке состояния сообщается, что вы видите прошлое состояние программы.
Исторический режим работает так: при каждой остановке программы DDD сохраняет текущую выполняемую позицию и отображаемые переменные. Также сохраняется информация о следе вызовов, нитях и регистрах, если открыты соответствующие диалоговые окна. При "отмене" команды выполнения DDD обновляет свой вид по этим сохраненным данным вместо обращения к программе.
Если вы хотите собирать такую информацию без прерывания программы ---
внутри цикла, к примеру, -- вы можете поставить точку останова с
командой cont
(см. раздел 5.1.8 Команды точек останова). Когда
достигается подобная точка останова, DDD останавливается, сохраняет
данные и выполняет команду `cont', продолжая выполнение. Используя
позднее `Undo', вы можете вернуться и посмотреть на каждую
отдельную итерацию цикла.
Чтобы покинуть исторический режим, можно применять команду `Redo' до тех пор, пока не вернетесь к текущему состоянию программы. Однако, любая команда DDD, которая ссылается на состояние программы, также сразу выводит из исторического режима, применяясь к текущему состоянию программы. Например, `Up' сразу покидает исторический режим и выбирает другой фрейм в восстановленном текущем состоянии программы.
Если вы хотите увидеть историю конкретной переменной, как она записана во время остановок программы, вы можете ввести команду DDD
graph history имя
Она вернет список всех ранее записанных значений переменной имя в форме массива. Обратите внимание: чтобы значения переменной имя сохранялись, она должна отображаться при останове программы.
В некоторых операционных системах одна программа может иметь более одной нити выполнения. Точная семантика нитей меняется от системы к системе, но в общем нити одной программы подобны нескольким процессам --- за исключением того, что они разделяют одно адресное пространство (то есть они могут считывать и изменять одни и те же переменные). С другой стороны, каждая нить имеет свои собственные регистры и стек выполнения и, возможно, личную память.
Для целей отладки DDD позволяет получать список активных в данный момент нитей и выбирать текущую нить -- на которой фокусируется отладка. Всю информацию о программе DDD показывает с точки зрения текущей нити.(26)
Чтобы получить список всех активных в текущий момент нитей вашей программы, выберите `Status => Threads'. Текущая нить подсвечивается. Чтобы сделать какую-то нить текущей, выберите ее.
При использовании JDB доступны дополнительные функции:
Для получения более подробной информации о нитях, смотрите документацию JDB и GDB (см. раздел `Debugging Programs with Multiple Threads' в Debugging with GDB).
Сигнал -- это асинхронное событие, которое может произойти в программе.
Операционная система определяет возможные виды сигналов и дает каждому
виду имя и номер. Например, SIGINT
в UNIX -- это сигнал,
который программа получает, когда вы нажимаете клавишу прерывания;
SIGSEGV
-- это сигнал, который программа получает, когда
ссылается на место в памяти, находящееся за пределами используемых
областей; SIGALRM
случается, когда истекает таймер (что
происходит, только если программа запросила сигнал по таймеру).
Некоторые сигналы, включая SIGALRM
, -- обычная часть работы
программы. Другие, такие как SIGSEGV
, указывают на ошибки; эти
сигналы фатальны (сразу уничтожают программу), если программа
заранее не определила другой способ их обработки. SIGINT
не
указывает на ошибку в программе, но обычно он фатален, так что может
служить для прерывания: для уничтожения программы.
GDB умеет детектировать любое появление сигнала в программе. Вы можете заранее сказать GDB, что нужно делать для каждого вида сигналов.
Обычно DDD настроен на игнорирование сигналов, не указывающих на
ошибку, вроде SIGALRM
(чтобы не вмешиваться в их роль в работе
программы), но он сразу останавливает вашу программу, когда приходит
сигнал ошибки. В DDD, вы можете просматривать и редактировать эти
установки через `Status => Signals'.
`Status => Signals' выводит панель, где показаны все виды сигналов, а также как GDB обрабатывает каждый из них. Для каждого сигнала доступны такие установки:
Stop
Print
Pass
Пункт `All Signals' особый. Изменение установки для него
влияет на все сигналы сразу -- кроме тех, что используются
отладчиком, обычно это SIGTRAP
и SIGINT
.
Чтобы отменить все изменения, используйте `Edit => Undo'. Кнопка `Reset' восстанавливает сохраненные параметры.
Когда сигнал останавливает вашу программу, он невидим, пока вы не продолжите выполнение. Затем программа видит сигнал, если в этот момент для данного сигнала действует установка `Pass'. Другими словами, после того как GDB сообщает о сигнале, вы можете изменить установку `Pass' в `Status => Signals' и контролировать таким образом, увидит программа сигнал или нет после продолжения.
Вы также можете сделать так, чтобы программа увидела сигнал, который она обычно не видит, или послать ей любой сигнал в любое время. Кнопка `Send' продолжит выполнение с того места, где программа остановилась, но сразу же пошлет ей указанный сигнал.
С другой стороны, вы также можете сделать так, чтобы программа не видела какой-то сигнал. Например, если программа остановилась из-за ошибки при обращении к памяти, вы могли бы записать в поврежденные переменные правильные значения и продолжить, надеясь увидеть дальнейшее выполнение; но программа, вероятно, может сразу же завершиться, если увидит этот фатальный сигнал. Чтобы предотвратить это, вы можете продолжить выполнение с помощью `Commands => Continue Without Signal'.
`Edit => Save Options' не сохраняет измененные установки для сигналов, поскольку они обычно бывают полезны только для какого-то одного проекта. Вместо этого установки сохраняются с текущим сеансом при использовании `File => Save Session As'.
Вы можете в любое время уничтожить процесс отлаживаемой программы с помощью кнопки `Kill'.
Уничтожение процесса бывает полезно, если вы хотите отлаживать дамп памяти, а не работающий процесс. GDB игнорирует дампы памяти, если ваша программа выполняется.
Кнопка `Kill' также полезна, если вы хотите перекомпилировать и перекомпоновать программу, поскольку на многих системах нельзя изменить выполняемый файл, когда он работает в каком-то процессе. В этом случае, когда вы в следующий раз щелкните на `Run', GDB заметит, что файл изменился, и считает таблицу символов заново (стараясь в то же время сохранить текущее состояние отладчика).
DDD предоставляет некоторые базовые средства для редактирования и перекомпиляции исходного кода, а также для наложения заплат на исполняемые файлы и файлы с дампами памяти.
Вы не можете изменять текущий отображаемый файл в самом DDD. Вместо этого DDD позволяет вам вызвать текстовый редактор. Чтобы вызвать текстовый редактор для текущего исходного файла, нажмите кнопку `Edit' или выберите `Source => Edit Source'.
По умолчанию DDD пробует запустить несколько распространенных редакторов. Вы можете настроить DDD на использование вашего любимого редактора; См. раздел 9.1.1 Настройка редактирования, для получения подробностей.
После выхода из редактора отображение исходного кода автоматически обновляется.
Если у вас параллельно запущены и DDD, и редактор, вы также можете обновлять исходный код вручную через `Source => Reload Source'. Это перезагружает отображаемый код из исходного файла. Поскольку DDD автоматически перезагружает исходный код при перекомпиляции отлаживаемой программы, ручная перегрузка редко бывает нужна.
Вы можете указать, каким редактором вы предпочитаете пользоваться, через `Edit => Preferences => Helpers => Edit Sources'. С этой установкой связан такой ресурс:
$XEDITOR
, потом
$EDITOR
, потом vi
:
Ddd*editCommand: \ ${XEDITOR-false} +@LINE@ @FILE@ || \ xterm -e ${EDITOR-vi} +@LINE@ @FILE@
Ниже показана установка из `~/.ddd/init' для вызова сеанса
редактирования в редакторе XEmacs с запущенным gnuserv
:
Ddd*editCommand: gnuclient +@LINE@ @FILE@
Эта установка из `~/.ddd/init' вызывает сеанс
редактирования в редакторе Emacs с запущенным emacsserver
:
Ddd*editCommand: emacsclient +@LINE@ @FILE@
Это экспериментальный ресурс:
Для перекомпиляции исходного кода с помощью make
вы можете
выбрать `File => Make'. Всплывет диалоговое окно, где вы
можете ввести цель Make -- как правило, это имя исполняемого
файла. Щелчок на кнопке `Make' вызывает программу make
с
указанной целью.
Кнопка `Make' на панели команд повторно вызывает make
с
последними использованными аргументами.
При использовании GDB вы можете открыть исполняемый код вашей программы (и файл с дампом памяти) как для чтения, так и для записи. Это позволяет изменять машинный код, так что вы можете намеренно накладывать заплаты на исполняемый файл вашей программы. Например, вы можете захотеть выставить внутренние отладочные флаги или даже сделать аварийные исправления.
Чтобы наложить заплату на двоичный файл, включите `Edit => GDB Settings => Writing into executable and core files'. Тогда GDB будет открывать исполняемые файлы и дампы памяти и для чтения, и для записи. Если вы уже загрузили файл, вы должны загрузить его снова (с помощью `Edit => Open File' или `Edit => Open Core'), чтобы новая установка возымела силу.
Не забудьте выключить `Writing into executable and core files' как можно скорее, чтобы предотвратить неумышленное изменение машинного кода.
Основные цели использования отладчика состоят в том, чтобы вы могли остановить свою программу до того, как она завершится, или чтобы в том случае, если в вашей программе возникнут проблемы, вы могли выяснить их причины.
Внутри DDD, программа может остановиться по нескольким причинам: по сигналу, на точке останова или при достижении следующей строки после команды DDD, такой как `Step'. Тогда вы можете исследовать и изменить значения, установить новые точки останова или удалить старые, а затем продолжить выполнение.
Подчиненные отладчики поддерживают два механизма останова программы при определенных событиях:
Точки останова можно устанавливать по позиции или по имени.
Точки останова устанавливаются в определенной позиции программы.
Если исходная строка видима, щелкните слева от нее первой кнопкой мыши, а потом на кнопке `Break'.
Или более быстрый способ: просто нажмите слева от исходной строки третью кнопку мыши и выберите из всплывающего меню пункт `Set Breakpoint'.
А есть еще более быстрый способ: для установки точки останова просто дважды щелкните слева от исходной строки.
В качестве еще одной альтернативы, вы можете выбрать `Source => Breakpoints'. Щелкните на кнопке `Break' и введите позицию.
(Если вас смущает такое количество разных способов, помните, что пользователи DDD делятся на три категории, и поддерживать нужно их всех. Новички изучают DDD и могут предпочитать использовать одну-единственную кнопку мыши. Продвинутые пользователи знают, как применять клавиатурные эквиваленты, и предпочитают всплывающие меню. Опытные пользователи предпочитают интерфейс командной строки.)
Точки останова обозначаются простым знаком "стоп" или как `#n', где n -- это номер точки останова. Затененный знак "стоп" (или `_n_') обозначает выключенную точку останова. Знак "стоп" с вопросительным знаком (или `?n?') обозначает условную точку останова или точку останова с установленным счетчиком пропусков.
Если вы установили точку останова по ошибке, удалите ее с помощью `Edit => Undo'.
Если видимо имя функции, щелкните на нем первой кнопкой мыши. Оно будет скопировано в поле аргумента. Затем щелкните на кнопку `Break', чтобы установить на этой функции точку останова.
Более быстрый способ: просто нажмите на имени функции первую кнопку мыши и выберите из всплывающего меню пункт `Break at'.
Есть еще более быстрый способ: щелкните на `Break...' из редактора точек останова (который вызывается через `Source => Breakpoints') и введите имя функции.
При использовании GDB вы также можете установить точку останова на всех функциях, соответствующих заданной строке. `Break => Set Breakpoints at Regexp ()' устанавливает точку останова на всех функциях, чьи имена соответствуют указанному в `()' регулярному выражению. Вот несколько примеров:
Чтобы удалить видимую точку останова, щелкните на ней первой кнопкой мыши. Ее позиция будет скопирована в поле аргумента. Затем нажмите кнопку `Clear', чтобы удалить точку останова в этой позиции.
Если видимо имя функции, щелкните на нем первой кнопкой мыши. Оно будет скопировано в поле аргумента. Для удаления точки останова щелкните на кнопку `Clear'.
Другой способ, более быстрый: вы можете просто нажать на кнопке останова третью кнопку мыши и выбрать из всплывающего меню пункт `Delete Breakpoint'.
Есть еще более быстрый вариант: можно выделить точку останова и нажать на `Delete' в редакторе точек останова (он вызывается через `Source => Breakpoints').
И самый быстрый способ -- это просто дважды щелкнуть на точке останова, удерживая клавишу Ctrl.
Вместо того чтобы удалять точку останова или наблюдения вы можете предпочесть выключить ее. При этом точка останова не действует, как если бы ее удалили, но информация о ней запоминается, так что позднее вы сможете снова включить ее.(12)
Чтобы выключить точку останова, нажмите на ее символе третью кнопку мыши и выберите из появившегося всплывающего меню пункт `Disable Breakpoint'. Чтобы снова включить ее, выберите пункт `Enable Breakpoint'.
Другой способ: вы можете выделить точку останова и щелкнуть на `Disable' или `Enable' в редакторе точек останова (который вызывается через `Source => Breakpoints'.
Выключенные точки останова обозначаются серыми знаками "стоп" или как `_n_', где n -- это номер данной точки останова.
Пункт меню `Disable Breakpoint' также доступен по кнопке `Clear'. Чтобы вызвать всплывающее меню, просто нажмите и удерживайте на этой кнопке первую кнопку мыши.
Временная точка останова удаляется сразу, как только достигнута.(13)
Чтобы установить временную точку останова, нажмите третью кнопку мыши слева от исходной строки и выберите из всплывающего меню пункт `Set Temporary Breakpoint'.
Есть более быстрый способ: просто дважды щелкните слева от исходной строки, удерживая нажатой клавишу Ctrl.
Временные точки останова бывают удобны, когда нужно прогнать программу до какой-то позиции: просто установите в этом месте временную точку останова и продолжите выполнение.
`Continue Until Here' из всплывающего меню устанавливает временную точку останова слева от исходной строки и сразу возобновляет выполнение. Программа останавливается, когда достигнута эта точка.
Пункты `Set Temporary Breakpoint' и `Continue Until Here' также доступны по кнопке `Break'. Чтобы вызвать всплывающее меню, нажмите и удерживайте на этой кнопке первую кнопку мыши.
Вы можете изменить все свойства точки останова, нажав на ее символе третью кнопку мыши и выбрав из всплывающего меню пункт `Properties'. Появится диалог, в котором показаны текущие свойства выбранной точки останова.
Есть более быстрый способ: можно просто дважды щелкнуть на точке останова.
Простейший вид точек останова прерывает выполнение программы всякий раз, когда она достигает указанного места. Но кроме этого, вы можете задать условие точки останова. Условие -- это просто булевское выражение на языке вашей программы. Точка останова с условием вычисляет это выражение всякий раз, когда программа достигает ее, и выполнение останавливается, только если условие истинно.
Это противоположность операторов контроля; в этом случае вы хотите, чтобы выполнение остановилось, когда контрольное утверждение нарушено --- то есть, когда условие ложно. В Си, если вы хотите проверить утверждение, выражаемое условием утверждение, вы должны установить в соответствующей точке останова условие `!утверждение'.
Условия останова могут обладать побочными эффектами и даже могут вызывать функции вашей программы. Это может быть полезно, к примеру, для запуска функций, которые ведут протокол работы программы, или для применения ваших собственных функций печати, которые форматируют какие-то особые структуры данных. Результаты полностью предсказуемы, если только по тому же адресу нет других включенных точек останова. (В такой ситуации DDD может сначала заметить другую точку останова и остановить программу, не проверяя условие.)
Обратите внимание на то, что для получения побочных эффектов команды точек останова обычно более удобны и гибки. См. раздел 5.1.8 Команды точек останова, для дополнительной информации.
Особый случай условия точки останова -- останов только тогда, когда эта точка достигалась определенное число раз. Это настолько полезно, что для такого случая есть специальный метод, использующий счетчик пропусков точки останова. У каждой точки останова есть счетчик пропусков; это целое число. Чаще всего оно равно нулю и поэтому эффекта от него нет. Но если ваша программа достигла точки останова с положительным счетчиком пропусков, то вместо останова производится уменьшение счетчика на единицу, а выполнение программы продолжается. В результате, если значение счетчика пропусков равно n, то в этой точке не будет останова еще n раз.
Вы можете задать счетчик пропусков в поле `Ignore Count' из панели свойств точки останова.(15)
Если у точки останова есть положительный счетчик пропусков и условие, то условие не проверяется. Как только счетчик пропусков достигает нуля, DDD начинает проверять условие.
Вы можете присвоить любой точке останова (или наблюдения) последовательность команд DDD, которые нужно выполнить, когда программа останавливается в этой точке. Например, вы можете захотеть напечатать значения некоторых выражений или включить другие точки останова.(16)
Вы можете отредактировать эти команды с помощью кнопок `Commands' из панели свойств точки останова.
Чтобы отредактировать команды точки останова, щелкните на `Edit >>' и введите команды в редакторе команд. Завершив редактирование, щелкните на `Edit <<', чтобы закрыть редактор.
При использовании GDB вы можете также записать последовательность команд для выполнения. Чтобы записать последовательность команд, выполните такие три шага:
Чтобы переместить точку останова в другое место, нажмите на знаке "стоп" первую кнопку мыши и перенесите его в желаемую позицию.(17) Это эквивалентно удалению точки останова в старой позиции и установке ее в новой. Новая точка останова наследует все свойства старой, кроме номера.
Чтобы скопировать точку останова в новую позицию, при переносе удерживайте нажатой клавишу Shift.
Если вы хотите найти какую-то точку останова, нажмите `Source => Breakpoints => Lookup'. Когда вы выберете точку останова из списка и щелкните на кнопке `Lookup', будет показана позиция, где находится эта точка.
Или вы можете ввести в поле аргумента `#n', где n --- это номер точки останова, и нажать кнопку `Lookup', чтобы найти ее определение.
Чтобы просмотреть и отредактировать все точки останова одновременно, выберите `Source => Breakpoints'. Появится редактор, который показывает состояние всех точек останова.
В редакторе вы можете выбирать отдельные точки останова, щелкая на них. Если при щелчке держать нажатой клавишу Ctrl, выделение переключается. Чтобы отредактировать свойства всех выделенных точек останова, щелкните на `Props'.
При использовании GDB через консоль отладчика можно вызывать еще несколько команд, связанных с точками останова:
hbreak позиция
thbreak позиция
См. раздел `Setting Breakpoints' в Debugging with GDB, для дополнительной информации.
Вы можете сделать так, чтобы программа останавливалась, когда изменяется значение какой-то переменной, или когда значение переменной считывается или записывается. Это называется установкой на переменной точки наблюдения.(18)
Точки наблюдения имеют много общего с точками останова: в частности, вы можете включать и выключать их. Также, вы можете устанавливать условия, счетчики пропусков и команды, которые должны выполняться, когда наблюдаемое значение изменяется.
Пожалуйста, обратите внимание: на архитектурах без специальной поддержки точек наблюдения они замедляют программу на два порядка. Это происходит, потому что подчиненный отладчик должен прерывать программу после каждой машинной инструкции, чтобы проверить, не изменилась ли наблюдаемая величина. Однако, эта задержка может оправдать себя при поиске ошибок, если вы даже не представляете какую часть программы подозревать.
Если имя переменной видимо, щелкните на нем первой кнопкой мыши. Имя будет скопировано в поле аргумента. В противном случае, сами введите имя переменной в поле аргумента. Чтобы установить точку наблюдения, нажмите кнопку `Watch'.
При использовании GDB вы можете устанавливать разные типы точек наблюдения. Чтобы получить меню, нажмите и удерживайте первую кнопку мыши на кнопке `Watch'.
Чтобы изменить свойства точки наблюдения, введите имя наблюдаемой переменной в поле аргумента. Нажмите и удерживайте первую кнопку мыши на кнопке `Watch' и выберите `Watchpoint Properties'.
Панель свойств точки наблюдения предоставляет такую же функциональность, что и панель свойств точки останова (см. раздел 5.1.5 Редактирование свойств точки останова). Есть дополнительная возможность: вы можете щелкнуть на `Print', чтобы увидеть текущее значение наблюдаемой переменной.
Чтобы просмотреть и отредактировать все точки наблюдения сразу, выберите `Data => Watchpoints'. Появится редактор, который показывает состояние всех точек наблюдения.
Редактор точек наблюдения предоставляет такую же функциональность, как редактор точек останова (см. раздел 5.1.11 Редактирование всех точек останова). В качестве дополнительной возможности, вы можете нажать кнопку `Print', чтобы увидеть текущее значение наблюдаемой переменной.
Чтобы удалить точку наблюдения, введите имя наблюдаемой переменной в поле аргумента и нажмите кнопку `Unwatch'.
Если программа уже запущена (см. раздел 6. Запуск программы), вы можете в любое время
прервать ее, нажав кнопку `Interrupt' или набрав в окне DDD
ESC.(19) При использовании GDB это эквивалентно
посыланию сигнала SIGINT
.
`Interrupt' и ESC также прерывают запущенную команду отладчика, такую как печать данных.
Если ваша программа является модальным приложением X Windows, DDD может прервать ее, когда она захватила указатель мыши, и ваш дальнейший диалог станет невозможен -- X-дисплей не будет отвечать на действия пользователя.
По умолчанию после каждого события DDD проверяет, не захвачен ли указатель мыши. Если он захвачен, DDD продолжает программу, чтобы вы могли использовать X-дисплей.
Это работает так: когда программа останавливается, DDD проверяет, нет ли событий ввода, таких как ввод с клавиатуры или мыши. Если DDD не получает никаких событий в течение следующих пяти секунд, он проверяет, не захвачен ли указатель мыши, пробуя захватить и отдать его. Если эта попытка неудачна, DDD решает, что указатель захвачен.
К сожалению, DDD не может определить, какая программа захватила указатель мыши, -- это может быть отлаживаемая программа, а может и другая. Поэтому дается еще десять секунд, чтобы вы могли отменить автоматическое продолжение программы.
Есть одна ситуация, когда это не сработает: если вы запрете X-дисплей при работающем DDD, DDD посчитает, что захват указателя случился из-за работы программы, -- и автоматически продолжит выполнение. Поэтому вы можете выключить эту возможность через `Edit => Preferences => General => Continue Automatically when Mouse Pointer is Frozen'.
Проверка захвата контролируется следующими ресурсами:
5000
,
или пять секунд.
cont
, что означает продолжение отлаживаемой программы. Также
можно написать kill
(уничтожить отлаживаемую программу) или
quit
(выйти из DDD).
10000
, или десять
секунд.
Перейти к: a - b - c - d - e - f - g - h - i - j - l - m - n - o - p - q - r - s - t - u - v - w - x
В DDD (и в данном руководстве) Ladebug рассматривается как вариант DBX. Это значит, что все сказанное относительно DBX также применимо и к Ladebug, если явно не сказано иное.
XDB не будет сопровождаться в будущих выпусках DDD. Используйте вместо него последнюю версию GDB.
В вашей системе могут получиться другие числа и другое поведение.
Если вы не видите здесь
подсказки `(gdb)', вызовите DDD заново с ключом --gdb
(см. раздел 2.1.1 Выбор подчиненного отладчика).
Только если включено.
Если в сеанс не включается дамп памяти, отображения данных DDD сохраняются как отложенные; то есть они будут восстановлены, как только выполнение программы достигнет той области видимости, в которой они были созданы. См. раздел 7.3.1.1 Создание единичных отображений, для получения подробностей.
Для этого требуется X11R6 или более поздняя версия.
Если вы используете файл ресурсов по умолчанию `Ddd', вы не сможете сопровождать одновременно несколько версий DDD. Именно поэтому подходящий файл `Ddd' обычно вкомпилирован в исполняемый файл DDD.
Если вы используете DDD для отладки сценариев на Perl или Python, этот раздел к вам не относится.
При использовании XDB и некоторых вариантов DBX отлаживаемую программу нужно обязательно указывать при запуске, и сменить ее во время работы нельзя.
JDB, PYDB и Perl не поддерживают дампов памяти.
JDB не поддерживает выключение точек останова.
JDB не поддерживает временные точки останова.
GDB не предоставляет способа сделать точку останова опять не временной.
JDB, Perl и некоторые варианты DBX не поддерживают счетчики пропусков.
JDB, PYDB и некоторые варианты DBX не поддерживают команды точек останова.
Когда глифы выключены (см. раздел 4.4 Настройка окна исходного кода), точки останова нельзя переносить. Вместо этого точку останова нужно удалить и снова поставить в другом месте.
Точки наблюдения доступны только в GDB и некоторых вариантах DBX. В XDB, похожее средство предоставляется контрольными утверждениями; подробности смотрите в документации по XDB.
Если Ctrl+C не привязан к операции копирования (см. раздел 3.1.11.2 Настройка меню Edit), вы также можете прервать программу с помощью Ctrl+C.
Если
отлаживаемая программа работает в отдельном окне выполнения, значение
TERM
для нее устанавливается в соответствии с ресурсом
`termType'; См. раздел 6.2.1 Настройка окна выполнения, для получения
подробностей.
В JDB окно выполнения недоступно.
JDB, PYDB и Perl не поддерживают подсоединение отладчика к работающему процессу.
JDB, PYDB и Perl не поддерживают изменение выполняемой позиции.
Когда глифы выключены (см. раздел 4.4 Настройка окна исходного кода), перенос выполняемой позиции невозможен, ее нужно устанавливать явно.
Perl не позволяет изменять текущий фрейм стека.
На данный момент нити поддерживаются только в GDB и JDB.
Для этого отладчику необходимо знать полный размер массива.
JDB не поддерживает изменение значений переменных.
Это строка `//'; его можно изменить через ресурс `labelDelimiter'. См. раздел 10.4.1 Настройка кнопок, для получения подробностей.
valign()
подобна halign()
, но
строит вертикальное выравнивание.
Окно машинного кода доступно только при использовании GDB.
Окно регистров доступно только при использовании GDB и некоторых вариантов DBX.
Если вы используете внутри определения команды DDD или включаете в него команды отладчика, которые возобновляют выполнение, то такие команды понимаются как автокоманды -- то есть они не выполняются непосредственно подчиненным отладчиком, а посылают командную строку DDD. Затем DDD интерпретирует эту командную строку и посылает подчиненному отладчику, возможно, добавив какие-то команды в начало, чтобы DDD мог потом обновить состояние. См. раздел 10.5.3 Определение команд с использованием других отладчиков.
Поскольку подчиненный отладчик вызывается через виртуальный терминал, стандартный поток ошибок обычно перенаправлен на стандартный вывод, так что DDD никогда не получает от подчиненного отладчика сообщений с потока ошибок.
This document was generated on December, 29 2000 using texi2html
Как и всякий хороший гражданин X Windows, DDD поставляется с большим файлом ресурсов по умолчанию, называемым `Ddd'. Данное приложение описывает действия и изображения, на которые ссылается `Ddd', чтобы вы могли легко изменить их.
Перечисленные ниже действия DDD можно использовать в таблицах перевода.
Эти действия используются в редакторе графов DDD.
select
. Привязано к
событию отпускания кнопки.
select
. Привязано к
событию перемещения указателя.
select
, но еще обновляет текущий аргумент.
select-or-move
, но еще обновляет текущий аргумент.
extend
, но еще обновляет текущий аргумент.
extend-or-move
, но также обновляет текущий аргумент.
toggle
, но также обновляет текущий аргумент.
toggle-or-move
, но также обновляет текущий аргумент.
graph
|node
|shortcut
])
graph
вызывает меню с глобальными
операциями над графами, node
вызывает меню с операциями над
вершинами, а shortcut
вызывает меню с операциями для быстрого
создания отображений.
Если аргумент не задан, вызывается контекстное меню: когда указатель
находится над вершиной, и нажата клавиша Shift, используется
shortcut
; когда указатель над вершиной, но клавиша Shift не
нажата, используется node
; иначе это действие ведет себя так, как
если бы был задан аргумент graph
.
any
|both
|from
|to
])
any
означает обработать все связки, где
выделена исходная или целевая вершина. both
означает обработать
все связки, где выделены обе вершины. from
означает обработать
все связки, где выделена хотя бы исходная вершина. to
означает
обработать все связки, где выделена хотя бы целевая вершина. По
умолчанию any
.
regular
|compact
], [[+
|-
] угол])
regular
означает, что нужно использовать
обыкновенный алгоритм компоновки; compact
использует
альтернативный алгоритм, где потомки помещаются рядом с предками. По
умолчанию применяется regular
. угол указывает, в каком
направлении следует компоновать граф. По умолчанию это текущее
направление графа.
-ячейка
, в текущем размере сетки.
+
|-
]угол])
+90
.
any
|both
|from
|to
])
any
означает обработать все связки,
где выделена исходная или целевая вершина. both
означает
обработать все связки, где выделены обе вершины. from
означает
обработать все связки, где выделена хотя бы исходная вершина. to
означает обработать все связки, где выделена хотя бы целевая вершина.
По умолчанию any
.
Следующие действия используются в консоли отладчика и других текстовых полях.
gdb-control
, но работает только в том случае, если курсор
находится в конце строки. Иначе управляющий-знак игнорируется, а
знак после курсора удаляется. Привязано к Ctrl+D.
gdb-control(^C)
.
действие(аргументы...)
в окне
исходного кода; если действие не задано, выполнить
`self-insert()'.
Motif
,
выполнить `beginning-of-line'. Иначе, выполнить `select-all'.
Привязано к Ctrl+A.
Следующие действия используются в окнах исходного кода.
Вместе с DDD устанавливаются несколько изображений, которые можно использовать в качестве ресурсов-растров, просто задавая их символьные имена. Для изображений кнопок также устанавливаются три варианта:
-hi
обозначает подсвеченный вариант (указатель поверх
кнопки).
-arm
обозначает задействованный вариант (кнопку
нажали).
-xx
обозначает выключенный (нечувствительный) вариант.
Время от времени вы будете сталкиваться с ошибками в DDD. Хотя мы не можем обещать, что можем или будем исправлять их, и возможно, мы даже не согласимся, что это ошибка, но мы все равно хотим услышать об ошибках, с которыми вы столкнулись, на случай, если мы действительно захотим их исправить.
Чтобы дать нам возможность исправить ошибку, вы должны описать ее. Чтобы сделать это эффективно, вы должны знать, когда и как это делать.
Посылайте сообщения об ошибках DDD по электронной почте на адрес
bug-ddd@gnu.org
Перед отправкой сообщения попытайтесь выяснить, действительно ли причина ошибки исходит от DDD. Часто ошибки возникают из-за неполной или отсутствующей установки X или Motif, например, или из-за ошибок X-сервера или Motif. Если запустить DDD как
$ ddd --check-configuration
будут проверены распространенные причины проблемы, и вы получите некоторые подсказки о том, как их можно исправить.
Другой потенциальный источник проблем -- подчиненный отладчик; в них тоже время от времени встречаются ошибки. Чтобы выяснить, не происходит ли ошибка по вине подчиненного отладчика, запустите DDD так:
$ ddd --trace
При этом в процессе работы DDD диалог между ним и подчиненным
отладчиком показывается на стандартом потоке ошибок. (Если
--trace
не задан, диалог записывается в файл
`~/.ddd/log'; раздел 10.12.1 Запись протокола.) Сравните вывод отладчика с
выводом DDD и решите, кто из них неправ.
Вот несколько советов по составлению отчетов об ошибках:
Чтобы мы смогли исправить ошибку DDD, вы должны включить следующую информацию:
$ ddd --configurationЕсли это не сработает, пожалуйста, напишите по крайней мере версию DDD, тип вашей машины, а также имя и номер версии операционной системы.
Обязательно включайте эту информацию в каждое сообщение об ошибке.
Если что-то ломается, первый и самый важный источник информации -- это файл протокола DDD. В этом файле, создаваемом в `~/.ddd/log' (`~' обозначает ваш начальный каталог), записывается следующая информация:
-> текст
.
Эта информация, собранная в одном файле, дает вам (и любому сопроводителю DDD) первое впечатление о том, что может идти не так.
Создаваемые DDD протокольные файлы могут достигать больших объемов, так что вам, возможно, захочется выключить ведение протокола. В DDD нет явного средства для этого. Однако, вы можете легко создать символьную ссылку с `~/.ddd/log' на `/dev/null', чтобы протокольная информация исчезала. Введите в подсказке оболочки следующие команды:
$ cd $ rm .ddd/log $ ln -s /dev/null .ddd/log
Помните, однако, что если протокол не ведется, диагностика сильно затруднена; в случае возникновения неприятностей может быть трудно воспроизвести ошибку.
Если DDD скомпилирован с ключом -g
(см. раздел 4.1 Компиляция для отладки), вы можете вызвать для него отладчик -- даже сам DDD, если
хотите. В DDD есть особое меню `Maintenance', которое вызывает
GDB для работающего процесса DDD. См. раздел 3.1.9 Меню Menu, для
получения подробностей.
В дистрибутиве DDD поставляется файл `.gdbinit', с помощью которым можно отлаживать DDD. Помимо прочего, в нем определяются команды `ddd', которая подготавливает среду для отладки DDD, и `string', которая позволяет печатать содержимое строковых переменных DDD; просто используйте `print пер' и затем `string'.
Вы можете в любое время заставить DDD сбросить дамп памяти, послав
ему сигнал SIGUSR1
. DDD продолжает работу, а вы можете
исследовать файл с дампом в GDB.
При отладке DDD бывает полезно сделать так, чтобы DDD не
отлавливал фатальные ошибки. Этого можно достигнуть, выставив перед
запуском DDD переменную среды DDD_NO_SIGNAL_HANDLERS
.
Вы можете использовать перечисленные ниже дополнительные ресурсы для получения диагностики DDD. Большая их часть связана с ключами командной строки.
--check-configuration
.
--maintenance
.
--configuration
.
--fonts
.
--help
.
--license
.
$PAGER
,
less
или more
). См. раздел 2.1.2 Ключи DDD, описание ключа
--manual
.
--news
.
--version
.
--trace
.
Некоторые установки GDB крайне важны для корректной работы DDD. Вот эти установки и их правильные значения:
set height 0 set width 0 set verbose off set prompt (gdb)
DDD автоматически устанавливает эти значения при вызове GDB; если их изменить, возможны неполадки, особенно в отображении данных.
При отладке на уровне машинного кода с применением в качестве подчиненного отладчика GDB 4.12 или более раннего используйте команду `display /x $pc', чтобы гарантировать обновление значения счетчика инструкций при каждом останове программы. Можно также написать эту команду в `~/.gdbinit' или (даже лучше) поставить последнюю версию GDB.
Когда DDD используется для отладки паскалеобразных программ, он не делает правильных предположений о способе индексации массивов и всегда начинает считать с единицы.
С некоторыми версиями DBX (в частности, с Solaris DBX) для правильной интерпретации вывода DBX DDD удаляет из него комментарии в стиле Си и Си++. Это также относится к выводу отлаживаемой программы, когда он посылается на консоль отладчика. Этих проблем можно избежать, используя отдельное окно выполнения.
В некоторых версиях DBX (а именно, DEC DBX и AIX DBX) нет автоматического отображения данных. В качестве альтернативы, DDD использует для доступа к данным команду DBX `print'. Это означает, что имена переменных интерпретируются в соответствии с текущим фреймом; переменные вне текущего фрейма не могут отображаться.
Все ограничения DBX (см. раздел 10.14 Использование DDD с DBX) существуют и в Ladebug.
В XDB нет автоматического отображения данных. Чтобы обойти это, DDD использует для доступа к данным команду `p'. Это означает, что имена переменных интерпретируются в соответствии с текущим фреймом; переменные вне текущего фрейма не могут отображаться.
В JDB нет автоматического отображения данных. Чтобы обойти это, DDD использует для доступа к данным команду `dump'. Это означает, что имена переменных интерпретируются в соответствии с текущим фреймом; переменные вне текущего фрейма не могут отображаться.
Команды JDB `dump' и `print' не поддерживают вычисления выражений. Следовательно, вы не можете отображать произвольные выражения.
Разбор вывода JDB требует довольно много процессорного времени из-за
распознавания асинхронных подсказок (любая нить может в любое время
что-то напечатать, в том числе подсказки). Поэтому программа, которая
много выводит на консоль, скорее всего сильно замедлит работу DDD. В
этом случае запустите программу с ключом -debug
в отдельном
окне и подсоедините к ней JDB с помощью ключа -passwd
.
В Perl нет автоматического отображения данных. Чтобы обойти это, DDD использует для доступа к данным команду `x'. Это означает, что имена переменных интерпретируются в соответствии с текущим фреймом; переменные вне текущего фрейма не могут отображаться.
В DDD включены несколько хаков, позволяющих запускать DDD с LessTif, свободным клоном Motif, без потери функциональности. Поскольку двоичный файл DDD может быть динамически скомпонован и использован как с библиотекой OSF/Motif, так и с LessTif, эти хаки для Lesstif можно включать и выключать на время выполнения.
Включены ли хаки для Lesstif во время выполнения или нет, зависит от установки ресурса `lessTifVersion':
79
обозначает LessTif 0.79, а 1005
обозначает LessTif 1.5.
Если значение этого ресурса меньше 1000, что указывает на LessTif 0.99 или более ранний, DDD задействует зависящие от версии хаки, чтобы обойти ошибки и недостатки LessTif.
Если DDD был скомпонован с LessTif, по умолчанию принимается значение
макроса `LessTifVersion' из файла `<Xm/Xm.h>'. Если DDD
скомпонован с OSF/Motif, по умолчанию принимается 1000
, что
выключает все специфичные для LessTif хаки.
Чтобы установить ресурс `lessTifVersion' во время запуска DDD и
указать номер версии библиотеки LessTif, вы можете также использовать
ключ --lesstif-version
версия.
Принимаемое по умолчанию значение ресурса `lessTifVersion'
определяется библиотекой LessTif, с которой DDD был скомпонован (или
это 1000
, при компиляции с OSF/Motif). Поэтому вам обычно не
нужно беспокоиться о значении этого ресурса. Однако, если вы
используете динамически скомпонованный двоичный файл DDD не с той
библиотекой, с которой его компилировали, вы должны указать номер версии
этой библиотеки используя этот ресурс. (К сожалению, DDD не может
определять это во время выполнения.)
Вот некоторые сценарии для иллюстрации этой схемы:
--lesstif-version 88
.
--lesstif-version 1000
.
--lesstif-version 90
.
Чтобы выяснить, с какой версией LessTif или OSF/Motif был скомпилирован
DDD, вызовите его с ключом --configuration
.
В исходном коде DDD специфичные для LessTif хаки контролируются строкой `lesstif_version'.
Вы не нашли чего-то в этом руководстве? У вас есть материал, который хорошо бы добавить? Пожалуйста, присылайте любые предложения на адрес ddd@gnu.org.
Если вы хотите что-то добавить в DDD, пожалуйста присылайте свой код на ddd@gnu.org. Некоторые мысли о том, что можно сделать, вы найдете в файле `TODO' из дистрибутива DDD.
Ответы на часто задаваемые вопросы, не освещенные в этом руководстве, смотрите на веб-странице DDD.
Мы создали почтовую рассылку для общего обсуждения DDD. Если вам нужна помощь в решении проблем с DDD, здесь вы найдете нужных людей.
Чтобы послать письмо всем подписчикам рассылки, пишите по адресу
ddd@gnu.org
В этой рассылке также помещаются объявления о новых выпусках DDD. Если вы хотите подписаться на нее или получить дополнительную информацию, пошлите письмо на адрес
ddd-request@gnu.org
Последние объявления и другие новости о DDD можно прочитать также на веб-странице DDD.
Перейти к: ( - 3 - @ - a - b - c - d - e - f - g - h - i - k - l - m - n - o - p - q - r - s - t - u - v - w
Перейти к: c - d - e - f - h - l - r - s - t - u
Перейти к: c - d - f - g - h - k - m - p - q - r - s - t - u - z
Перейти к: . - c - d - i - j - l - s - t - ~
Перейти к: @ - А - М - П - С - Ф - a - b - c - e - f - g - h - i - j - l - m - n - p - r - s - t - v - x - а - б - в - г - д - з - и - к - л - м - н - о - п - р - с - т - у - ф - ш - э