У меня есть кроссплатформенное приложение C ++, которое разбито на несколько общих библиотек и загружает дополнительные функции из общих библиотек плагинов. Предполагается, что библиотеки плагинов являются автономными и функционируют сами по себе, без знания или зависимости от вызывающего приложения.
Один из плагинов содержит скопированный код из основного приложения, поэтому содержит имена символов, которые совпадают с именами в движке. (Да, я знаю, что обычно это нет-нет, но в то время, когда плагин был написан, движок был монолитным двоичным файлом и не мог совместно использовать библиотеки.) В Windows все работает нормально. В Linux мы получали segfaults. Посмотрев на трассировку стека ошибки, она возникла в плагине при вызове функций с повторяющимся именем класса. Похоже, это было результатом того, что движок и плагин имели несколько разные версии общего кода (некоторые функциональные возможности класса были закомментированы в плагине). Это было так, как будто плагин связывал свои символы времени выполнения с движком, а не со своим собственным. Мы «исправили» проблему, изменив параметры dlopen
на dlopen(pFilepath, RTLD_LAZY | RTLD_LOCAL)
.
Но когда мы переписали движок для разделения на разделяемые библиотеки (для возможного повторного использования в плагинах), мы снова получаем ошибку segfault. И, глядя на трассировку стека, он идет от двигателя -> плагин -> двигатель.
Есть ли способ указать для компоновщика времени выполнения, чтобы он не отображал символы плагина на движок (особенно, если они определены в плагине)?
Спасибо!
Matt
Отредактировано 2009-12-3
Сначала я попытался обернуть код плагина в его собственное пространство имен. Это не сработало, потому что оно статически связано с библиотекой, которая также связана с движком. Версии статической библиотеки разные, так что segfault!
Затем я изменил сборку движка и его библиотек, чтобы они были статически связаны. И когда я запускаю его, у меня больше нет проблемы. Таким образом, похоже, что это было результатом того, что символы общей библиотеки были экспортированы, а затем динамически перемещены в плагин, когда он был открыт. Но когда весь код движка находится в одном исполняемом файле, он не экспортирует свои символы (поэтому он не пытается переместить символы плагина в движок).
У меня все еще есть проблема, поскольку есть распараллеленная версия программы (использующая Open-MPI), и она все еще получает ошибку сегмента. Похоже, он все еще экспортирует символы движка и перемещает плагин. Это может быть связано с тем, как Open-MPI выполняет приложение.
Существуют ли какие-либо флаги компоновщика, которые можно было бы использовать в разделяемой библиотеке плагина, который бы указывал ей не динамически перемещать символы во время выполнения? Или скрыть символы, чтобы они не перемещались? Я пробовал -s
(«Опустить всю символьную информацию»), но это, очевидно, не изменило динамические символы (проверено с помощью nm -D <plugin>
).