Запускать приложение в GDB до возникновения исключения

102

Я работаю над многопоточным приложением и хочу отлаживать его с помощью GDB.

Проблема в том, что одна из моих тем продолжает умирать с сообщением:

pure virtual method called
terminate called without an active exception
Abort

Я знаю причину этого сообщения, но понятия не имею, где оно происходит в моей цепочке. Обратная трассировка действительно была бы полезна.

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

Анкур Сетхи
источник
О каком сигнале сообщает GDB при паузе? вы должны иметь возможность запускать такую ​​команду, какhandle SIGUSR1 pass noprint nostop
Hasturkun

Ответы:

148

Вы можете попробовать использовать "catchpoint" ( catch throw), чтобы остановить отладчик в точке, где генерируется исключение.

Следующий отрывок из руководства gdb описывает функцию точки перехвата.


5.1.3 Установка точек перехвата

Вы можете использовать точки перехвата, чтобы отладчик останавливался при определенных видах программных событий, таких как исключения C ++ или загрузка разделяемой библиотеки. Используйте команду catch, чтобы установить точку перехвата.

  • поймать событие

    Остановитесь, когда произойдет событие . событие может быть любым из следующих:

    • бросить

      Вызов исключения C ++.

    • поймать

      Перехват исключения C ++.

    • exec

      Вызов exec. В настоящее время это доступно только для HP-UX.

    • вилка

      Призыв к вилке. В настоящее время это доступно только для HP-UX.

    • vfork

      Звонок в vfork. В настоящее время это доступно только для HP-UX.

    • загрузить или загрузить имя библиотеки

      Динамическая загрузка любой разделяемой библиотеки или загрузка библиотеки libname. В настоящее время это доступно только для HP-UX.

    • выгрузить или выгрузить имя библиотеки

      Выгрузка любой динамически загружаемой разделяемой библиотеки или выгрузка библиотеки libname. В настоящее время это доступно только для HP-UX.

  • событие tcatch

    Установите точку перехвата, которая активна только для одной остановки. Точка перехвата автоматически удаляется после первого перехвата события.

Используйте info breakкоманду для вывода списка текущих точек перехвата.

В настоящее время существуют некоторые ограничения для обработки исключений C ++ (catch throw и catch catch) в GDB:

  • Если вы вызываете функцию в интерактивном режиме, GDB обычно возвращает вам управление, когда функция завершает выполнение. Однако, если вызов вызывает исключение, вызов может обойти механизм, который возвращает вам управление, и привести к тому, что ваша программа либо прервется, либо просто продолжит выполнение, пока не достигнет точки останова, не перехватит сигнал, который GDB ожидает, или завершится. Это так, даже если вы установили точку перехвата для исключения; точки перехвата исключений отключены в интерактивных вызовах.

  • Вы не можете создать исключение в интерактивном режиме.

  • Вы не можете установить обработчик исключений в интерактивном режиме.

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

Чтобы остановить работу непосредственно перед вызовом обработчика исключений, вам необходимо знать реализацию. В случае GNU C ++ исключения вызываются вызовом библиотечной функции с именем __raise_exception, которая имеет следующий интерфейс ANSI C:

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

Чтобы отладчик перехватил все исключения до того, как произойдет разворачивание стека, установите точку останова на __raise_exception (see section Точки останова; точки наблюдения; и исключения).

С условной точкой останова (см. Раздел «Условия останова»), которая зависит от значения id, вы можете остановить свою программу при возникновении определенного исключения. Вы можете использовать несколько условных точек останова, чтобы остановить вашу программу при возникновении любого из ряда исключений.

Дэн
источник
Вы также можете указать тип исключения для перехвата, например catch throw std::runtime_exception.
scai
5

Установите точку останова на __pure_virtual

Стив Фолли
источник
В ответе @JeffreyHill теперь он называется __cxa_pure_virtual. Я не знаю, как это проверить, поэтому не хочу редактировать ответ. Я не собираюсь голосовать против, но ответ сейчас может быть неправильным и должен быть отредактирован кем-то, кто знает, что правильно.
Филипп Классен,
5

FWIW, видимо, в gcc 4.1 изменилось соответствующее имя функции и в этой функции надо установить точку останова.

__cxa_pure_virtual

Джеффри Хилл
источник
0

Только ниже у меня работал с gdb 8.3:

break _Unwind_RaiseException

"catch throw" или "break __cxx_throw" у меня не работали.

сумен78
источник