Читать книгу 📗 "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:15041504 struct redirect *rp = NULL; /* Исполнение достигает контрольной точки */(gdb) <b>list</b> /* Показать исходный код */14991500 void1501 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)Команда
stepnextstepnextС другой стороны, когда вы используете с содержащим вызов функции оператором
stepstepnextЗАМЕЧАНИЕ. Легко забыть, какая команда была использована, и продолжать нажимать ENTER для выполнения последующих операторов. Если вы используете
stepstrlen()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}В заключение, команда
cont1520 for (numnodes = 0; tree != NULL; tree = tree->rnode)(gdb) <b>cont</b> /* Продолжить *!Continuing.hello, worldProgram exited normally. /* Сообщение от GDB */(gdb) <b>quit</b> /* Выйти из отладчика */Отслеживаемая точка (watchpoint) подобна контрольной точке, но используется для данных, а не для кода. Отслеживаемые точки устанавливаются для переменной (или поля структуры или объединения или элемента массива), при их изменении GDB посылает уведомления. GDB проверяет значение отслеживаемой точки по мере пошагового исполнения программы и останавливается при изменении значения. Например, переменная
do_lint_oldgawk--lint_oldgetopt_long()getopt_long()main.cgawkint 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