Как создать приложение, которое требует как libstdc ++. So.5, так и libstdc ++. So.6? - PullRequest
8 голосов
/ 31 октября 2009

Я хочу предварить это важным примечанием, что Я не программист на C / C ++ и знаю очень мало о том, как работает связывание библиотек в C.

Наш код использует libstdc ++. So.6 (gcc 3.4, я думаю). У нас есть сторонние предварительно скомпилированные (с закрытым исходным кодом) библиотеки, которые используют libstdc ++. So.5 (я думаю, что gcc 2.something или 3.2). Это на Linux. У нас есть как .a, так и .so версия сторонней библиотеки lib.

Возможно ли построить наше приложение с библиотеками сторонних разработчиков? Как? Возможно ли построить / запустить наше приложение без установки libstdc ++. So.5 наших машин, как?

Если я забыл некоторую важную информацию, пожалуйста, дайте мне знать - я едва знаю, что относится к этому материалу. Я понимаю, что полный ответ, вероятно, будет невозможен; Я действительно ищу направление и руководство. Статическое связывание этого, динамическое то, перестройте это, предварительно соберите то-то, переключитесь на версию x, или символическую ссылку на викторину и т. Д.

Обновление:

Мы попытались использовать dlopen с RTLD_LOCAL, чтобы изолировать стороннюю библиотеку от остальной части нашего приложения. Похоже, что в основном сработало, однако у нас остались большие утечки памяти по неизвестным причинам. Мы подозреваем, что, когда мы вызываем dlopen, сторонняя библиотека извлекает символы, такие как malloc из уже загруженного .so.6, и вещи запутываются.

Для хихиканья мы попытались поместить стороннюю библиотеку в LD_PRELOAD, затем запустили наше приложение, и утечки памяти, кажется, полностью исчезли.

Ответы [ 4 ]

7 голосов
/ 05 ноября 2009

Вы можете попытаться создать библиотеку-оболочку вокруг сторонней библиотеки: используйте статическую версию этой библиотеки + свяжите ее со стандартной статической библиотекой (-static-libgcc - убедитесь, что вы выбрали правильную версию через -L) , Важно правильно закрыть библиотеку-обертку, т. Е. Экспортировать должны только символы из исходной сторонней библиотеки, а все остальное следует скрыть. Таким образом, ваша библиотека-обертка будет отображать все необходимые символы для вашего приложения и инкапсулировать стандартные вещи внутри. Обратите внимание, что работа не гарантируется, особенно если некоторые операции с памятью распределяются между вашим кодом и кодом третьей стороны (например, вы выделяете память в своем коде и освобождаете в третьей стороне) ... в таком случае единственным вариантом может быть сохранение этой третьей party lib в другом пространстве процесса.

Я не думаю, что упомянутая выше динамическая опция сработает, потому что вы получите точно такую ​​же проблему - чуть позже.

В общем случае лучше не смешивать двоичные файлы с разными временами выполнения в одном и том же пространстве процесса. Это почти всегда рецепт катастрофы.

4 голосов
/ 02 ноября 2009

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

2 голосов
/ 31 октября 2009

Хотя легко связать libstdc ++. So.6 и libstdc ++. So.5 одновременно с вашим приложением одновременно, его поведение в значительной степени будет неопределенным, поскольку символы берутся из любой библиотеки в основном случайно.

Лучший путь к успеху IMO - это создать собственное приложение на основе сторонней библиотеки на старой системе (которая использует совместимый gcc, например, gcc 3.3) и позволить ему обмениваться данными с вашим основным приложением через IPC ( например, общая память). Таким образом, нет

Если вы не хотите хранить libstdc ++. So.5 в вашей целевой системе, то это просто: используйте флаг gcc -static, чтобы связать libstdc ++. A с вашим приложением-оболочкой.

1 голос
/ 07 ноября 2009

Хотя один из приведенных подходов может сработать, я думаю, что безопаснее сказать, что вы не можете сделать это напрямую надежным способом. Если вы напишите обертку с использованием полностью API на основе C (только C-совместимые структуры, память, управляемая malloc / free и т. Д.), То вы сможете использовать решение pobedim. Однако если вам нужно обмениваться структурами C ++, это небезопасно, поскольку, даже если вы могли бы создать ссылку, реализации разных стандартных библиотек могли бы использоваться для одних и тех же объектов. Кроме того, ABI C ++ может быть несовместим с основами кода на основе .5 и .6 (я точно не помню, как несколько лет назад произошло серьезное изменение ABI в Gnu C ++, связанное со звуковыми именами стандартной библиотеки).

Я думаю, что самый безопасный подход к решению этой проблемы - это использовать многопроцессорный подход с неким IPC между вашим приложением и процессом ресурсного / вычислительного сервера, построенным на рассматриваемой библиотеке. Вы можете использовать CORBA, D-Bus, Sun RPC или какой-то специальный протокол по каналам или сокетам для выполнения этой работы. Я сделал это, когда пытался использовать 32-битный код с закрытым исходным кодом в 64-битных приложениях, и он работает достаточно хорошо. Вы увидите снижение производительности, но вы также полностью обойдете проблемы, связанные с попыткой смешать среды выполнения C ++ в одном процессе.

...