Могу ли я установить точку останова на доступ к памяти в GDB?


244

Я запускаю приложение через GDB, и я хочу установить точку останова для любого доступа к определенной переменной / изменения. Есть хороший метод для этого? Я также был бы заинтересован в других способах мониторинга переменной в C / C ++, чтобы увидеть, если / когда она изменится.

Ответы:


286

смотреть только перерывы на запись, rwatch позволяет разбить на чтение, и смотреть позволяет разбивать при чтении / записи.

Вы можете установить точки наблюдения чтения в ячейках памяти:

gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface

но одно ограничение относится к командам rwatch и awatch; Вы не можете использовать переменные GDB в выражениях:

gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.

Таким образом, вы должны расширить их самостоятельно:

gdb$ print $ebx 
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f

Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()

Редактировать: Да, и кстати. Вам нужна либо аппаратная, либо программная поддержка . Программное обеспечение, очевидно, намного медленнее. Чтобы узнать, поддерживает ли ваша ОС аппаратные контрольные точки, вы можете посмотреть настройку среды can-use-hw-watchpoints .

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.

7
Если вы хотите посмотреть элемент метода C ++, я нашел этот вариант очень полезным: watch -location mTextFormatted.
Иван Вучица

Что если у меня нет адреса переменной? Могу ли я просто использовать его имя?
Раффи Хачадурян

5
Вы можете сделать так, чтобы GDB печатал адрес переменной с оператором address-of. print &variable
Лодувийк

1
Этот ответ ничего не говорит о размере ячейки памяти, за которой следят watchкоманды. Между тем, это первый вопрос, который приходит на ум после прочтения вышеизложенного. Сколько байтов rwatch *0xfeedfaceбудет на самом деле смотреть?
AnT

8
@AnT, я предполагал, что он будет смотреть один байт, что, кажется, имеет место, но вы можете привести его к определенному типу, например, rwatch *(int *)0xfeedfaceи он будет смотреть sizeof(int)байты: sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints. html
asksol

28

То, что вы ищете, называется сторожевой точкой .

использование

(gdb) watch foo: смотреть значение переменной foo

(gdb) watch *(int*)0x12345678: смотреть значение, указанное адресом , приведенное к любому типу, который вы хотите

(gdb) watch a*b + c/d: смотреть произвольно сложное выражение , действительное на родном языке программы

Точки наблюдения бывают трех видов:

  • смотреть : GDB будет перерыв , когда запись происходит
  • rwatch : GDB сломается, когда произойдет чтение
  • awatch : GDB сломается в обоих случаях

Вы можете выбрать более подходящий для ваших нужд.

Для получения дополнительной информации, проверьте это .


5
Я написал другой ответ, потому что существующие не казались мне очень простыми ...
Паоло М

25

Если предположить, что первый ответ ссылается на синтаксис, подобный C, (char *)(0x135700 +0xec1a04f)то ответ на этот вопрос rwatch *0x135700+0xec1a04fневерен. Правильный синтаксис есть rwatch *(0x135700+0xec1a04f).

Отсутствие ()там вызвало у меня сильную боль, пытаясь использовать точки наблюдения самостоятельно.


9

Я просто попробовал следующее:

 $ cat gdbtest.c
 int abc = 43;

 int main()
 {
   abc = 10;
 }
 $ gcc -g -o gdbtest gdbtest.c
 $ gdb gdbtest
 ...
 (gdb) watch abc
 Hardware watchpoint 1: abc
 (gdb) r
 Starting program: /home/mweerden/gdbtest 
 ...

 Old value = 43
 New value = 10
 main () at gdbtest.c:6
 6       }
 (gdb) quit

Так что это кажется возможным, но вам, кажется, нужна некоторая аппаратная поддержка.


Если ваша платформа не поддерживает аппаратные точки наблюдения, GDB должен вернуться к программной точке наблюдения.
Тод

2

Используйте watch, чтобы увидеть, когда записывается переменная, rwatch, когда она читается, и часы, когда она читается / записывается из / в, как отмечено выше. Тем не менее, обратите внимание, что для использования этой команды вы должны прервать выполнение программы, а переменная должна находиться в области видимости, когда вы нарушили программу:

Используйте команду watch. Аргументом команды watch является вычисляемое выражение. Это означает, что переменная, на которую вы хотите установить точку наблюдения, должна находиться в текущей области видимости. Итак, чтобы установить точку наблюдения для неглобальной переменной, вы должны установить точку останова, которая остановит вашу программу, когда переменная находится в области видимости. Вы устанавливаете точку наблюдения после остановки программы.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.