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
Другие вопросы по тегам