Запустіть програму в GDB, поки не стане виняток


102

Я працюю над багатопотоковою програмою, і хочу налагодити її за допомогою GDB.

Проблема в тому, що одна з моїх ниток продовжує вмирати з повідомленням:

pure virtual method called
terminate called without an active exception
Abort

Я знаю причину цього повідомлення, але я не маю уявлення, де в моїй темі воно відбувається. Назад, справді, було б корисно.

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


Який сигнал GDB звітує, коли він призупиняється? ви повинні мати можливість виконувати таку команду, якhandle SIGUSR1 pass noprint nostop
Hasturkun

Відповіді:


147

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

Наступний уривок із посібника gdb описує особливість точки вибору.


5.1.3 Встановлення точок лову

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

  • виловлювальний захід

    Зупиніться, коли відбудеться подія . подією може бути будь-яка з наступних:

    • кинути

      Кидок винятку C ++.

    • виловити

      Вилов винятку C ++.

    • виконувати

      Заклик до виконання. Наразі це доступно лише для HP-UX.

    • вилка

      Дзвінок на роздрібнення. Наразі це доступно лише для HP-UX.

    • vfork

      Заклик до vfork. Наразі це доступно лише для HP-UX.

    • load або load libname

      Динамічне завантаження будь-якої спільної бібліотеки або завантаження імені бібліотеки. Наразі це доступно лише для HP-UX.

    • вивантажувати або вивантажувати ліб-ім’я

      Вивантаження будь-якої динамічно завантаженої спільної бібліотеки або вивантаження імені бібліотеки. Наразі це доступно лише для HP-UX.

  • подія tcatch

    Встановіть точку лову, яку ввімкнено лише для однієї зупинки. Точка лову автоматично видаляється після першого впіймання події.

Використовуйте info breakкоманду для переліку поточних точок лову.

Наразі в GDB є обмеження щодо обробки винятків C ++ (викидання та вилов):

  • Якщо ви викликаєте функцію інтерактивно, 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, ви можете зупинити свою програму, коли буде піднято певний виняток. Ви можете використовувати кілька умовних точок зупинки, щоб зупинити свою програму, коли порушено будь-який з ряду винятків.


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

5

Встановіть точку розриву на __pure_virtual


У відповіді @JeffreyHill зараз вона називається __cxa_pure_virtual. Я не знаю, як це перевірити, тому не хочу редагувати відповідь. Я не маю наміру голосувати проти, але відповідь може бути неправильною зараз, і її повинен редагувати хтось, хто знає, що правильно.
Philipp Claßen

5

FWIW, мабуть, в gcc 4.1 відповідна назва функції змінилася, і в цій функції потрібно встановити точку розриву.

__cxa_pure_virtual


0

Лише нижче один працював для мене з gdb 8.3:

break _Unwind_RaiseException

"catch catch" або "break __cxx_throw" не працювали для мене.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.