Запустите приложение в GDB, пока не возникнет исключение - PullRequest
95 голосов
/ 12 июля 2009

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

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

pure virtual method called
terminate called without an active exception
Abort

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

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

Ответы [ 3 ]

140 голосов
/ 12 июля 2009

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

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


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

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

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

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

    • бросок

      Выдача исключения C ++.

    • поймать

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

    • * 1043 Exec *

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

    • вилка

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

    • vfork

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

    • load или load libname

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

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

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

  • tcatch event

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

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

В настоящее время существуют некоторые ограничения в обработке исключений C ++ (catch throw и 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 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 Точки останова; точки наблюдения и исключения).

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

5 голосов
/ 12 июля 2009

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

4 голосов
/ 29 августа 2014

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

__ cxa_pure_virtual

...