Переход через функцию с оператором throw внутри gdb не заставляет меня ловить оператор - PullRequest
5 голосов
/ 24 мая 2019

Я пытаюсь пройтись по программе на C ++.Он генерирует исключение на нижнем уровне, но я не могу заставить отладчик gdb привести меня к оператору catch.Один из обходных путей - зарегистрировать точки перехвата с (gdb) catch catch, но неудобно всегда помнить о необходимости делать это, и это приведет к остановке программы на каждой цепочке операторов перехвата на нижних уровнях.

Вот пример, иллюстрирующий мою точку зрения.Для этой программы, скомпилированной с g++ foo.cpp -g -o foo ..

#include <cstdio>

void f() {
    throw 42;
}
int main(int argc, char *argv[])
{
    try {
        throw 42;
        //f();
        printf("after throw\n");
    } catch (...) {
        printf("in catch stmt\n");
    }
    printf("after try-catch stmt\n");
}

.. GDB работает так, как я ожидал: когда я перехожу через оператор throw, следующим оператором является catch.

$ gdb -q foo
Reading symbols from foo...done.
(gdb) start
Temporary breakpoint 1 at 0x912: file foo.cpp, line 9.
Starting program: /home/dannas/foo
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdd88) at foo.cpp:9
9               throw 42;
(gdb) next
12          } catch (...) {
(gdb)
13              printf("in catch stmt\n");
(gdb)
in catch stmt
12          } catch (...) {

Но если я заменим оператор throw 42 в main на f(), тогда программа завершится, если я перейду f().

$ gdb -q foo
Reading symbols from foo...done.
(gdb) start
Temporary breakpoint 1 at 0x912: file foo.cpp, line 10.
Starting program: /home/dannas/foo

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdd78) at foo.cpp:10
10              f();
(gdb) n
in catch stmt
after try-catch stmt
[Inferior 1 (process 32522) exited normally]

Версии:

 $ gdb --version
 GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
 $ gcc --version
 gcc (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0

Том Трой говорит, что в https://stackoverflow.com/a/34601424/582010:

[...] есть специальный маркер отладки (либо функция, либо «зонд SDT», в зависимости откак все было построено) в низкоуровневом коде раскрутки, который используется при возникновении исключения.GDB ставит точку останова на этом месте.При достижении этой точки останова GDB проверяет целевой кадр стека броска и, если он находится выше кадра связи, устанавливает временную точку останова в качестве цели броска.

Вопрос

GDB не может знать, какую строку он будет выполнять дальше?Цитата выше, кажется, предполагает, что GDB пытается выяснить, какой следующий оператор основан на доступных обработчиках catch?Есть ли способ заставить отладчик вести себя так, как я ожидаю: «gdb останавливается при следующем выполнении оператора в функции при переходе»?

...