idx = 0}, hash = {next = 0x8095250, name = 0x0, length = 0, value = 0x0,
ref = 1}}, type = Node_expression_list, flags = 1}
В
заключение, команда
cont
(continue — продолжить) дает возможность продолжить выполнение программы. Она будет выполняться до следующей контрольной точки или до нормального завершения, если других контрольных точек нет. Этот пример продолжается с того места, на котором остановился предыдущий:
1520 for (numnodes = 0; tree != NULL; tree = tree->rnode)
(gdb) cont /* Продолжить *!
Continuing.
hello, world
Program exited normally. /* Сообщение от GDB */
(gdb) quit /* Выйти из отладчика */
Отслеживаемая точка (watchpoint) подобна контрольной точке, но используется для данных, а не для кода. Отслеживаемые точки устанавливаются для переменной (или поля структуры или объединения или элемента массива), при их изменении GDB посылает уведомления. GDB проверяет значение отслеживаемой точки по мере пошагового исполнения программы и останавливается при изменении значения. Например, переменная
do_lint_old
в
gawk
равна true, когда была использована опция
– -lint_old
. Эта переменная устанавливается в true функцией
getopt_long
. (Мы рассмотрели
getopt_long
в разделе 2.1.2 «Длинные опции GNU»). В файле
main.c
программы
gawk
:
int do_lint_old = FALSE;
/* предупредить о материале, не имевшейся в V7 awk */
...
static const struct option optab[] = {
...
{ "lint-old", no_argument, &do_lint_old, 1 },
...
};
Вот пример сеанса, показывающего отслеживаемую точку в действии:
$ gdb gawk /* Запустить GDB с gawk */
GNU gdb 5.3
...
(gdb) watch do_lint_old
/* Установить отслеживаемую точку для переменной */
Hardware watchpoint 1: do_lint_old
(gdb) run --lint-old 'BEGIN { print "hello, world" }'
/* Проверка отслеживаемой точки при работе программы */
Hardware watchpoint 1: do_lint_old
Hardware watchpoint 1: do_lint_old
Old value = 0 /* Отслеживаемая точка останавливает программу */
New value = 1
0x420c4219 in _getopt_internal from /lib/i686/libc.so.6
(gdb) where /* Трассировка стека */
#0 0x420c4219 in _getopt_internal from /lib/i686/libc.so.6
#1 0x420c4e83 in getopt_long from /lib/i686/libc.so.6
#2 0x080683a1 in main (argc=3, argv=0xbffff8a4) at main.c:293
#3 0x420158d4 in __libc_start_main from /lib/i686/libc.so.6
(gdb) quit /* На данный момент мы закончили */
The program is running. Exit anyway? (y or n) y /* Да */
GDB может делать гораздо больше, чем мы здесь показали. Хотя руководство GDB большое, его стоит прочесть целиком хотя бы один раз, чтобы ознакомиться с его командами и возможностями. После этого, возможно, будет достаточно просмотреть файл
NEWS
в каждом новом дистрибутиве GDB, чтобы узнать, что нового или что изменилось.
Стоит также распечатать справочную карточку GDB, которая поставляется в дистрибутиве GDB в файле
gdb/doc/refcard.tex
. Создать печатную версию справочной карточки для PostScript после извлечения исходника и запуска configure можно с помощью следующих команд:
$ cd gdb/doc /* Перейти о подкаталог doc */
$ make refcard.ps /* Отформатировать справочную карточку */
Предполагается, что справочная карточка будет распечатана с двух сторон листа бумаги 8,5×11 дюймов [168] (размер «letter») в горизонтальном (landscape) формате. В ней на шести колонках предоставлена сводка наиболее полезных команд GDB. Мы рекомендуем распечатать ее и поместить под своей клавиатурой при работе с GDB.
168
Примерно 213×275 мм — Примеч. перев.
15.4. Программирование для отладки
Имеется множество методик для упрощения отладки исходного кода, от простых до сложных. В данном разделе мы рассмотрим ряд из них.
15.4.1. Код отладки времени компилирования
Несколько методик относятся к самому исходному коду.
15.4.1.1. Использование отладочных макросов
Возможно, простейшей методикой времени компилирования является использование препроцессора для создания условно компилируемого кода. Например:
#ifdef DEBUG
fprintf(stderr, "myvar = %d\n", myvar);
fflush(stderr);
#endif /* DEBUG */
Добавление
– DDEBUG
к командной строке компилятора вызывает
fprintf
при выполнении программы.
Рекомендация: сообщения отладки посылайте в
stderr
, чтобы они не были потеряны в канале и чтобы их можно было перехватить при помощи перенаправления ввода/вывода. Убедитесь, что использовали