Как выполнить определенное действие, когда в GDB достигнута определенная точка останова? - PullRequest
48 голосов
/ 29 июня 2011

Я ищу способ сделать какое-нибудь действие, когда конкретная точка останова попадает в GDB.

По сути, в моей программе есть некоторые утечки памяти.Когда срабатывает функция malloc и free, мне нужно войти в функцию (шаг) и собрать некоторую базовую информацию, такую ​​как addr и size (в основном, вывести там значения).После этого возобновите мою программу.

У нас есть какой-нибудь хороший способ сделать это?

Ответы [ 3 ]

55 голосов
/ 29 июня 2011

Например, вот как вы можете использовать команды точки останова для вывода значения x при входе в foo всякий раз, когда x положительно.

break foo if x>0
commands
silent
printf "x is %d\n",x
cont
end

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

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

break 403
commands
silent
set x = y + 4
cont
end
48 голосов
/ 01 ноября 2013

Чтобы прояснить ответ Фредрика, commands (или просто command, кажется) автоматически знает, что вы просто установили точку останова. То есть то, что показывает Фредрик, - это не многострочная команда break, а две отдельные команды: break и commands. Это выглядит так:

(gdb) break 989 
Breakpoint 23 at 0x7fffe2761dac: file foo.cpp, line 989.
(gdb) command
Type commands for breakpoint(s) 23, one per line.
End with a line saying just "end".
>silent
>print result
>end
(gdb) c
Continuing.
$79 = {elems = {0, 0}}
(gdb) 
7 голосов

dprintf (Динамический printf)

https://sourceware.org/gdb/onlinedocs/gdb/Dynamic-Printf.html

Это наиболее удобное решение для конкретного случая печати вещей:

dprintf <line>, "%u\n", variable

Он также может быть быстрее, чем commands, поскольку он может компилировать и вставлять код, вместо того, чтобы возвращать управление GDB для интерпретации произвольных командных строк.ТОДО Я не знаю, если это на самом деле сделано.dprintf против commands: В чем разница между dprintf и break + командами + продолжить?

Подробный пример:

main.c

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    uint32_t i;
    uint32_t r = 0;
    for (i = 0; i < 10; ++i) {
        r += i*i + 13*r*i + 17;   /* LINE 10. */
    }
    printf("%" PRIu32 "\n", r);
    return EXIT_SUCCESS;
}

Тогда:

gcc -ggdb3 -O0 -std=c99 -o main main.c
gdb -batch -nh -q -ex 'dprintf 10, "%u %u\n", i, r' -ex 'run' ./main

Выход:

Dprintf 1 at 0x400545: file main.c, line 10.
0 0
1 17
2 256
3 6933
4 277346
5 14699371
6 970158528
7 3628079733
8 3070853710
9 317092431
3057168588
[Inferior 1 (process 14305) exited normally]

Протестировано в Ubuntu 16.04, GDB 8.2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...