8

我想以重要的通知作为开头,我不是 C/C++ 程序员,并且对库的链接如何在 C 中工作知之甚少。

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

是否可以使用 3rd 方库构建我们的应用程序?如何?是否可以在没有 libstdc++.so.5 安装我们的机器的情况下构建/运行我们的应用程序,如何?

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

更新:

我们尝试使用dlopenwithRTLD_LOCAL将 3rd 方库与我们应用程序的其余部分隔离开来。这似乎大部分都有效,但是,由于未知原因,我们留下了大量的内存泄漏。我们怀疑,当我们调用.so.6 时,dlopen第三方库会malloc从已加载的 .so.6 中提取符号,而事情会变得混乱。

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

4

4 回答 4

7

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

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

一般来说,最好不要在同一进程空间中混合具有不同运行时间的二进制文件。这几乎总是灾难的根源。

于 2009-11-05T17:57:38.267 回答
4

向您的供应商索取更新版本的库,该版本使用的东西不会非常过时。如果做不到这一点,您可以查看您的新应用程序是否仍可与旧版本的库一起使用,并在必要时将其移植回来。尝试拥有同一个库的两个不同版本会很痛苦,我认为您不会找到可接受的解决方案。

于 2009-11-02T19:31:14.960 回答
2

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

成功的最佳方式 IMO 是在旧系统(使用兼容的 gcc,例如 gcc 3.3)上围绕您的 3rd 方库构建自己的应用程序,并让它通过 IPC 与您的主应用程序通信(例如共享记忆)。这样一来,不

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

于 2009-10-31T19:45:31.317 回答
1

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

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

于 2009-11-07T19:15:24.087 回答