Gdb останавливается со слишком большим количеством точек наблюдения, когда есть только один

Знаете ли вы какие-либо другие причины, по которым точка наблюдения не может быть вставлена ​​иначе, чем слишком много аппаратных точек останова/точек наблюдения?

У меня есть следующий сеанс отладки:

GNU gdb (GDB) 7.1
...
(gdb) watch itrap_t_beg[1][222]
Hardware watchpoint 1: itrap_t_beg[1][222]
(gdb) cont
Continuing.
...
Hardware watchpoint 1: itrap_t_beg[1][222]

...
(gdb) cont
Continuing.
Warning:
Could not insert hardware watchpoint 1.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.

(gdb) info break
Num     Type           Disp Enb Address            What
1       hw watchpoint  keep y                      itrap_t_beg[1][222]
        breakpoint already hit 1 time

Как вы можете видеть, есть только одна точка наблюдения, но она не может вставить точку останова.

Знаете ли вы, как я могу это исправить?

Ответы

Ответ 1

Насколько я знаю, процессоры x86 для процессоров имеют четыре

Ответ 2

Может заставлять программные точки останова (которые не имеют ограничения по размеру), запустив

set can-use-hw-watchpoints 0

Ответ 3

Ответ на съемку: используйте watch -location itrap_t_beg[1][222] или короткую форму watch -l.

Длинный ответ: Цитата руководства GDB:

Просмотр сложных выражений, которые ссылаются на многие переменные, также может исчерпывать ресурсы, доступные для сторожевых точек с аппаратным обеспечением. Это потому, что gdb нужно смотреть каждую переменную в выражении с отдельными выделенными ресурсами.

gdb буквально наблюдает за самим выражением, а не за любой адрес, на который он указывает. В этом случае это означает, что точка останова попадет, если сама itrap_t_beg будет изменена так, что itrap_t_beg[1][222] делает; там не только точка наблюдения для itrap_t_beg[1][222], но и одна для itrap_t_beg. Это может быть больше, чем доступно.

В вашем случае itrap_t_beg - 7 ints, 28 байт. Контрольная точка x86_64 имеет длину до восьми байтов, поэтому для всей системы GDB требуется четыре точки наблюдения - плюс пятая для itrap_t_beg. Семейство x86 поддерживает только четыре одновременных точки наблюдения.

Более подробный пример того, как работают точки наблюдения:

//set a watchpoint on '*p' before running
#include <stdio.h>
int a = 0;
int b = 0;
int c = 0;
int* p = &a;

int main()
{
    puts("Hi"); // Dummy lines to make the results clearer, watchpoints stop at the line after the change
    *p = 1; // Breaks: *p was changed from 0 to 1
    puts("Hi");
    a = 2; // Breaks: a is *p, which changed from 1 to 2
    puts("Hi");
    p = &b; // Breaks: p is now b, changing *p from 2 to 0
    puts("Hi");
    p = &c; // Doesn't break: while p changed, *p is still 0
    puts("Hi");
    p = NULL; // Breaks: *p is now unreadable
    puts("Hi");
    return 0;
}

В теории это полезная функция; вы можете наблюдать сложное выражение, ломающееся, как только оно ложно, несколько похожее на постоянно проверенное утверждение. Например, вы можете watch a==b в вышеуказанной программе.

На практике это неожиданно, часто вызывает эту проблему, и обычно это не то, что вы хотите.

Чтобы посмотреть только адрес цели, используйте watch -location itrap_t_beg[1][222]. (Это доступно в GDB 7.3, выпущенном в июле 2011 года, если вы все еще на 7.1, используйте print &itrap_t_beg[1][222] и watch *(itrap_t)0x12345678, или какой бы адрес он не печатал.)