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

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

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

pure virtual method called
terminate called without an active exception
Abort

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

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

Ответ 1

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

Следующий отрывок В руководстве gdb описывается функция catchpoint.


5.1.3 Настройка точек удержания

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

  • событие catch

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

    • бросок

      Выбрасывание исключения С++.

    • улов

      Улавливание исключения С++.

    • Exec

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

    • вилка

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

    • vfork

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

    • загрузить или загрузить libname

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

    • выгрузить или выгрузить libname

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

  • Событие tcatch

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

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

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

* If you call a function interactively, GDB normally returns control to you when the function has finished executing. If the call raises an exception, however, the call may bypass the mechanism that returns control to you and cause your program either to abort or to simply continue running until it hits a breakpoint, catches a signal that GDB is listening for, or exits. This is the case even if you set a catchpoint for the exception; catchpoints on exceptions are disabled within interactive calls.

* You cannot raise an exception interactively.

* You cannot install an exception handler interactively. 

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

Чтобы остановить работу перед вызовом обработчика исключений, вам понадобятся некоторые сведения о реализации. В случае с GNU С++ исключения возникают путем вызова библиотечной функции с именем __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 (см. раздел "Точки останова, точки наблюдения и исключения" ).

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

Ответ 2

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

Ответ 3

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

__ cxa_pure_virtual