Исключения в Linux из общего объекта (.so)

У меня есть тестовая программа под названием ftest. Он загружает.so файлы, которые содержат тесты, и запускает найденные там тесты. Один из этих тестов загружает и запускает.so, который содержит драйвер базы данных Postgres для нашего O/RM.

Когда драйвер Postgres генерирует исключение, которое определено в этом файле.so (или том, на которое он ссылается, но ftest не ссылается на него) и перехватывается тестовой средой, деструктор исключения вызывает ошибку сегмента.

Этот segfault происходит всякий раз, когда скомпилированное исключение находится в.so, который был динамически загружен (используя dload).

Подобные вещи прекрасно работают в Windows, которая имеет такую ​​же архитектуру. На самом деле мы не хотим ограничивать себя использованием только исключений из базовых библиотек - надстройки должны иметь возможность создавать свои собственные классы исключений и обрабатывать их как обычно.

Исключениями являются подклассы std::exception. Иногда исключения могут быть определены в библиотеках (таких как libpqxx), что означает, что исключения также иногда находятся вне нашего контроля.

Исключения создаются с использованием чего-то вроде:

throw exception_class( exception_arguments );

И ловятся с помощью:

catch ( std::exception &e ) {
    // handler code
}

Есть ли какая-то специальная опция компилятора, необходимая, чтобы это работало? Нужно ли нам переключаться, чтобы генерировать исключения через throw new exception_class( args ) (мы не хотим этого делать)?

1 ответ

Решение

Предполагая, что вы используете gcc -

Добавьте -Wl,-E при сборке исполняемого файла, вызывающего dlload(). Это экспортирует все символы типа информации из исполняемого файла, что должно позволить RTTI (при перехвате исключения) работать должным образом.

VC++ использует сравнения строк для соответствия typeinfo, что приводит к более медленной динамической трансляции<> и т. Д., Но меньшим двоичным файлам. g++ использует сравнения указателей.

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

В сети также есть несколько статей, касающихся этой темы.

надеюсь, это поможет, Хейман.

Другие вопросы по тегам