проблема g ++: исключение не обнаружено - PullRequest
3 голосов
/ 22 сентября 2009

Ситуация такова, что у меня есть динамическая библиотека, написанная на C ++, которая обернута для Python другой динамической библиотекой, также написанной на C ++ (генерируемой SIP, если быть точным). Первая динамическая библиотека определяет функцию do_raise, которая выдает исключение RaiserError, подкласс std::exception. Вторая динамическая библиотека в оболочке do_raise пытается перехватить RaiserError, чтобы перевести ее в исключение Python.

Сборка с Visual C ++, все работает как положено, и RaiserError перехватывается правильно. Однако при использовании g ++ в Linux RaiserError не перехватывается. Если я попытаюсь поймать std::exception (базовый класс RaiserError), это сработает. Что здесь не так? У двух библиотек разные понятия типа RaiserError, поскольку он не распознается блоком catch?

Для тестирования я также пишу небольшой исполняемый файл, который вызывает do_raise в библиотеке C ++, и здесь я могу поймать RaiserError даже с g ++.

Ответы [ 4 ]

3 голосов
/ 22 сентября 2009

Вы не можете надежно передавать исключения C ++ через границы модуля. В Windows (по крайней мере для 32-битных процессов) для этого есть стандартный ABI, но с gcc вам не повезло.

2 голосов
/ 22 сентября 2009

Я считаю, что GCC использует какой-то указатель на информацию о типе, и если он не совпадает с указателем, то типы не совпадают.

Это звучит как один из случаев, когда Microsoft C ++ возвращается к строковому сравнению информации о типе (медленно, но работает). Это не поможет вам с GCC.

Вы можете попытаться убедиться, что класс исключений не скрыт и что typeinfo видна в ELF-файле .so. Попробуйте убедиться, что тип определен только в одном .so.

Редактировать: Я только что подумал об этом: я считаю, что динамические линкеры ELF прекрасно работают с несколькими копиями символов typeinfo и выберут одну копию для использования. Я думаю, что вы можете получить несколько копий, если вы связали некоторый статический код или сделали -Bsymbolic в одном из .so или исполняемых файлов.

1 голос
/ 15 октября 2009

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

Что-то не связанное с поиском, может ли какой-то из ваших деструкторов вызывать исключение: если вы бросаете новое исключение в деструктор, разматывая стек и выбрасывает первое исключение, ваша программа будет прервана, независимо от попыток / ловушек переноса , С g ++ сообщение об ошибке выглядит так же, как если бы вы не уловили первое исключение. Осторожно выполните шаг раскручивания стопки, чтобы увидеть, может ли это произойти с вами.

0 голосов
/ 23 сентября 2009

Как и в других ответах, проблема в том, что (более чем вероятно) отсутствует информация RTTI в .so.

Попробуйте добавить -Wl, -E к вашим флагам компилятора, это заставит компоновщик экспортировать необходимыеинформация о типе.

VC ++ использует сравнения строк (в отличие от сравнения указателей) для сопоставления типов (во время динамического приведения, отлова и т. д.), это медленнее во время выполнения, но приводит к меньшим DLL (из-за уменьшения RTTI, экспортируемого вthe dll's).

Это будет надежно до тех пор, пока вы используете один и тот же компилятор для компиляции ваших общих объектов (или вы используете независимый от поставщика ABI, доступный с g ++> = 4.3).

...