Я работаю над многопоточным приложением и хочу отладить его с помощью GDB.
Проблема в том, что один из моих потоков продолжает умирать с сообщением:
pure virtual method called
terminate called without an active exception
Abort
Я знаю причину этого сообщения, но понятия не имею, где в моем потоке оно возникает. Отслеживание было бы очень полезно.
Когда я запускаю свое приложение в GDB, оно приостанавливается каждый раз, когда поток приостанавливается или возобновляется. Я хочу, чтобы мое приложение продолжало работать нормально, пока один из потоков не умрет с этим исключением, в этот момент все должно остановиться, чтобы я мог получить обратную трассировку.
Вы можете попробовать использовать "точку захвата" (catch throw
), чтобы остановить отладчик в точке, где генерируется исключение.
Следующая выдержка из руководства gdb описывает функцию catchpoint.
5.1.3 Установка точек захвата
Вы можете использовать точки перехвата, чтобы заставить отладчик останавливаться при определенных видах программных событий, таких как исключения C++ или загрузка разделяемой библиотеки. Для установки точки перехвата используйте команду catch.
catch event
Остановиться, когда произойдет событие. событием может быть любое из следующих:
throw
Выбрасывание исключения из C++.
catch
Перехват исключения C++.
exec
Вызов команды exec. В настоящее время это доступно только для HP-UX.
fork
Вызов команды fork. В настоящее время это доступно только для HP-UX.
vfork
Вызов vfork. В настоящее время это доступно только для HP-UX.
load or load libname
Динамическая загрузка любой разделяемой библиотеки или загрузка библиотеки libname. В настоящее время это доступно только для HP-UX.
выгрузить или выгрузить libname
Выгрузка любой динамически загруженной разделяемой библиотеки или выгрузка библиотеки libname. В настоящее время это доступно только для HP-UX.
Устанавливает точку захвата, которая включается только для одной остановки. Точка перехвата автоматически удаляется после первого перехвата события.
Используйте команду info break
для получения списка текущих точек перехвата.
В настоящее время существуют некоторые ограничения на обработку исключений C++ (catch throw и catch catch catch) в GDB:
Если вы вызываете функцию в интерактивном режиме, GDB обычно возвращает вам управление, когда функция завершает выполнение. Однако если вызов вызывает исключение, он может обойти механизм, возвращающий управление, и привести к прерыванию работы программы или просто к продолжению выполнения до тех пор, пока она не попадет в точку останова, не поймает сигнал, который прослушивает GDB, или не выйдет из программы. Это произойдет, даже если вы установите точку перехвата для исключения; точки перехвата исключений отключены в интерактивных вызовах.
Вы не можете вызвать исключение в интерактивном режиме.
Вы не можете установить обработчик исключений в интерактивном режиме.
Иногда 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 (см. раздел Точки останова, точки наблюдения и исключения).
С помощью условной точки останова (см. раздел Условия останова), которая зависит от значения id, вы можете остановить свою программу при возникновении определенного исключения. Вы можете использовать несколько условных точек останова, чтобы остановить программу при возникновении любого из нескольких исключений.
Установите точку останова на __pure_virtual
FWIW, по-видимому, в gcc 4.1 имя соответствующей функции изменилось, и необходимо установить точку останова в этой функции.
__cxa_pure_virtual