如何构建一个既需要libstdc ++。so.5又需要libstdc ++。so.6的应用程序?

时间:2009-10-31 19:15:44

标签: gcc build linker libstdc++

我想在前面加上我不是C / C ++程序员的重要通知,并且知道很少关于库的链接如何在C中工作< / p>

我们的代码使用libstdc ++。so.6(gcc 3.4,我认为)。我们有第三方预编译(闭源)库使用libstdc ++。so.5(gcc 2.something或3.2,我认为)。这是在Linux上。我们有第三方lib的.a和.so版本。

是否可以使用第三方库构建我们的应用程序?怎么样?是否有可能在没有libstdc ++的情况下构建/运行我们的应用程序.so.5安装了我们的机器,怎么样?

如果我忘记了一些重要信息,请告诉我 - 我几乎不知道这些东西是什么。我意识到完全答案可能是不可能的;我真的在寻找方向和指导。静态链接,动态,重建,预建某某,切换到版本x,或符号链接quizdoodle等。

更新

我们尝试将dlopenRTLD_LOCAL一起使用,将第三方库与我们应用的其余部分隔离开来。这似乎主要工作,但是,由于未知原因,我们留下了大量内存泄漏。我们怀疑,当我们调用dlopen时,第三方库会从已经加载的.so.6中提取malloc之类的符号,并且事情变得混乱。

对于咯咯笑,我们尝试将第三方库放入LD_PRELOAD,然后运行我们的应用程序,内存泄漏似乎完全消失。

4 个答案:

答案 0 :(得分:7)

您可以尝试围绕第三方库构建包装库:使用该库的静态版本+将其与静态标准库链接(-static-libgcc - 确保通过-L获取正确的版本) 。重要的是要正确关闭这个包装库,即只导出原始第三方库中的符号,其他一切都应该被隐藏。这样,包装器库将为您的应用程序公开所有需要的符号,并将标准内容封装在其中。请注意,如果您的代码和第三方代码之间共享一些内存操作(例如,您在代码中分配内存并在第三方中释放),则无法保证可以正常工作...在这种情况下,唯一的选择是保持第3代在不同的进程空间中举办派对。

我不认为上面提到的动态选项会起作用,因为你会得到完全相同的问题 - 只是稍后。

通常,最好不要在同一进程空间中混合具有不同运行时间的二进制文件。它几乎总是一种灾难。

答案 1 :(得分:4)

向您的供应商询问该库的较新版本,该版本使用的东西并非过时。如果做不到这一点,你可以看到你的新应用程序是否仍然适用于旧版本的库,如果需要,可以将其移回。试图拥有同一个库的两个不同版本会让人感到痛苦,我认为你找不到合适的解决方案。

答案 2 :(得分:2)

虽然很容易将libstdc ++。so.6和libstdc ++。so.5同时链接到你的应用程序,但它的行为几乎是未定义的,因为符号基本上是偶然从这两个库中获取的。

成功的最佳方式IMO是在旧系统(使用兼容的gcc,例如gcc 3.3)上围绕第三方lib构建自己的应用程序,并让它通过IPC与您的主应用程序通信(例如,共享内存)。这样,没有

如果您不想在目标系统上保留libstdc ++。so.5,那么这很简单:使用g​​cc的-static标志将libstdc ++。a链接到您的包装器应用程序。

答案 3 :(得分:1)

虽然到目前为止给出的方法之一可能有效,但我认为说你不能直接以可靠的方式做到这一点更安全。如果你使用完全基于C的API编写一个包装器(只有C兼容的结构,由malloc / free管理的内存等),那么你可以使用pobedim的解决方案。但是,如果需要交换C ++结构,那么它就不安全了,即使你可以使链接发生,也会在同一个对象上使用不同的标准库实现。此外,C ++ ABI可能在基于.5和.6的代码库之间不兼容(我不记得几年前主要的Gnu C ++ ABI发生了多少与标准库sonames相关的变化)。

我认为解决这个问题最安全的方法是在您的应用程序和构建在相关库上的资源/计算服务器进程之间使用多进程方法和某种IPC。您可以使用CORBA,D-Bus,Sun RPC或管道或套接字上的某些ad-hoc协议来完成这项工作。当我尝试在64位应用程序中使用闭源32位代码时,我已经完成了这项工作,并且它运行良好。您将看到性能损失,但您也将完全回避尝试在单个进程中混合使用C ++运行时所固有的问题。