GDB: Как заставить точку наблюдения не удаляться после возврата функции?
Контрольные точки на локальных переменных функции обычно удаляются при возврате функции с сообщением "Контрольная точка 7 удалена, потому что программа оставила блок в". Иллюстрация:
struct mystruct{
int a, b, c;
};
void MyFunc(){
mystruct obj;
obj.a = 2;
}
int main(){
MyFunc();
}
пример сеанса GDB
(gdb) b 7
Breakpoint 1 at 0x4004f1: file /tmp/test2.cpp, line 7.
(gdb) r
Starting program: /tmp/test2
Breakpoint 1, MyFunc () at /tmp/test2.cpp:7
7 obj.a = 2;
(gdb) wa obj
Hardware watchpoint 2: obj
(gdb) c
Continuing.
Hardware watchpoint 2: obj
Old value = {a = 4195600, b = 0, c = 4195328}
New value = {a = 2, b = 0, c = 4195328}
MyFunc () at /tmp/test2.cpp:8
8 }
(gdb) c
Continuing.
Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
main () at /tmp/test2.cpp:12
12 }
Я пробовал кастовать как wa *(mystruct *)&obj
а также wa *(mystruct *)(void*)&obj
, но безрезультатно.
Мне это нужно, потому что GDB на встроенном устройстве ARM, с которым я работаю, сломан: иногда он удаляет точку наблюдения без причины; обратная трассировка выглядит как линии, помеченные "??" знаки и сообщение о поврежденном стеке. Хотя приложение на самом деле хорошо.
1 ответ
Как говорит GDB: установка точек наблюдения,
GDB автоматически удаляет контрольные точки, которые отслеживают локальные (автоматические) переменные, или выражения, которые включают в себя такие переменные, когда они выходят из области видимости, то есть когда выполнение покидает блок, в котором были определены эти переменные.
Однако, начиная с версии 7.3 (спасибо @Hi-Angel и пользовательским паркам на IRC за указание на это; я упустил возможность увидеть это прямо в документации), watch
команда принимает -location
аргумент:
Обычно точка наблюдения учитывает область видимости переменных в выражении (см. Ниже). Аргумент -location указывает GDB вместо этого наблюдать за памятью, на которую ссылается expr. В этом случае GDB оценит expr, возьмет адрес результата и просмотрит память по этому адресу. Тип результата используется для определения размера просматриваемой памяти.
На старых версиях GDB вы можете запустить это вместо этого, используя пример из вашего вопроса:
eval "watch *(mystruct *)%p", &obj
Обратите внимание, что просмотр местоположений в стеке может привести к ложным уведомлениям, если просматриваемая память повторно используется локальными переменными другой функции.
В качестве альтернативы вы можете автоматизировать установку точки наблюдения для автоматической переменной, которая постоянно входит и выходит из области видимости. Установите точку останова в точке, где она находится в области видимости - например, в начале функции или блока, в которой она объявлена, - затем присоедините watch
а также continue
команда:
(gdb) break MyFunc
(gdb) commands $bpnum
>watch obj
>continue
>end