Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
GNU gdb 5.3
...
(gdb) <b>break do_print</b> /* Прерывание в do_print */
Breakpoint 1 at 0x805a36a: file builtin.c, line 1504.
(gdb) <b>run 'BEGIN { print "hello, world" }'</b> /* Запуск программы */
Starting program: /home/arnold/Gnu/gawk/gawk-3.1.3/gawk 'BEGIN { print "hello, world" }'
Breakpoint 1, do_print (tree=0x8095290) at builtin.c:1504
1504 struct redirect *rp = NULL; /* Исполнение достигает контрольной точки */
(gdb) <b>list</b> /* Показать исходный код */
1499
1500 void
1501 do_print(register NODE *tree)
1502 {
1503 register NODE **t;
1504 struct redirect *rp = NULL;
1505 register FILE *fp;
1506 int numnodes, i;
1507 NODE *save;
1508 NODE *tval;
По достижении контрольной точки вы проходите программу в пошаговом режиме. Это означает, что GDB разрешает программе исполнять лишь по одному оператору исходного кода за раз. GDB выводит строку, которую собирается выполнить, и выводит приглашение. Чтобы выполнить оператор, используется команда
next
(gdb) <b>next</b> /* Выполнить текущий оператор (строка 1504 выше) */
1510 fp = redirect_to_fp(tree->rnode, &rp); /* GDB выводит следующий оператор */
(gdb) /* Нажмите ENTER для его выполнения и перехода к следующему */
1511 if (fp == NULL)
(gdb) /* снова ENTER */
1519 save = tree = tree->lnode; (gdb) /* И снова */
1520 for (numnodes = 0; tree != NULL; tree = tree->rnode)
Команда
step
next
step
next
С другой стороны, когда вы используете с содержащим вызов функции оператором
step
step
next
ЗАМЕЧАНИЕ. Легко забыть, какая команда была использована, и продолжать нажимать ENTER для выполнения последующих операторов. Если вы используете
step
strlen()
printf()
finish
Вывести содержимое памяти можно с использованием команды
print
(gdb) <b>print *save</b> /* Вывести структуру, на которую указывает save */
$1 = {sub = {nodep = {l = {lptr = 0x8095250, param_name = 0x8095250 "pRtb",
l1 = 134828624}, r = {rptr = 0x0, pptr = 0, preg = 0x0,
hd = 0x0, av = 0x0, r_ent =0}, x = {extra = 0x0, x1 = 0,
param_list = 0x0},
name = 0x0, number = 1, reflags = 0}, val = {
fltnum = 6.6614191194446594e-316, sp = 0x0, slen = 0, sref = 1,
idx = 0}, hash = {next = 0x8095250, name = 0x0, length = 0, value = 0x0,
ref = 1}}, type = Node_expression_list, flags = 1}
В заключение, команда
cont
1520 for (numnodes = 0; tree != NULL; tree = tree->rnode)
(gdb) <b>cont</b> /* Продолжить *!
Continuing.
hello, world
Program exited normally. /* Сообщение от GDB */
(gdb) <b>quit</b> /* Выйти из отладчика */
Отслеживаемая точка (watchpoint) подобна контрольной точке, но используется для данных, а не для кода. Отслеживаемые точки устанавливаются для переменной (или поля структуры или объединения или элемента массива), при их изменении GDB посылает уведомления. GDB проверяет значение отслеживаемой точки по мере пошагового исполнения программы и останавливается при изменении значения. Например, переменная
do_lint_old
gawk
--lint_old
getopt_long()
getopt_long()
main.c
gawk
int do_lint_old = FALSE;
/* предупредить о материале, не имевшейся в V7 awk */
...
static const struct option optab[] = {
...
{ "lint-old", no_argument, &do_lint_old, 1 },
...
};
Вот пример сеанса, показывающего отслеживаемую точку в действии:
$ <b>gdb gawk</b> /* Запустить GDB с gawk */
GNU gdb 5.3