如何构建同时需要 libstdc++.so.5 和 libstdc++.so.6 的应用程序?
我想在本文开头指出一个重要的注意事项:我不是 C/C++ 程序员,并且对 C 中库的链接如何工作知之甚少。
我们的代码使用 libstdc++ .so.6(我认为是 gcc 3.4)。我们有使用 libstdc++.so.5 的第三方预编译(闭源)库(我认为是 gcc 2.something 或 3.2)。这是在linux上的。我们有 .a 和 .so 版本的第三方库。
是否可以使用第三方库构建我们的应用程序?如何?是否可以在没有安装 libstdc++.so.5 我们的机器的情况下构建/运行我们的应用程序,如何?
如果我忘记了一些重要信息,请告诉我 - 我几乎不知道与此内容相关的内容。我意识到一个完整的答案可能是不可能的;我真的在寻找方向和指导。静态链接这个、动态那个、重建那个、预构建某某、切换到版本 x 或符号链接测验涂鸦等。
更新:
我们尝试将 dlopen
与 RTLD_LOCAL
一起使用> 将第 3 方库与我们应用程序的其余部分隔离。这似乎大部分有效,但是,由于未知的原因,我们留下了大量的内存泄漏。我们怀疑,当我们调用 dlopen 时,第三方库会从已加载的 .so.6 中提取诸如 malloc 之类的符号,事情就会变得混乱。
为了咯咯笑,我们尝试将第三方库放入 LD_PRELOAD 中,然后运行我们的应用程序,内存泄漏似乎完全消失了。
I want to preface this with the important notice that I am not a C/C++ programmer, and know very little about how linkage of libraries works in C.
Our code uses libstdc++.so.6 (gcc 3.4, i think). We have third-party precompiled (closed source) libraries that use libstdc++.so.5 (gcc 2.something or 3.2, i think). This is on linux. We have both a .a and .so version of the third party lib.
Is it possible to build our app with the 3rd party libs? How? Is it possible to build/run our app without having libstdc++.so.5 installed our our machines, how?
If I've forgotten some critical information, please let me know - I hardly know whats relevant with this stuff. I realize that a complete answer probably won't be possible; I'm really looking for direction and guidance. Static link this, dynamic that, rebuild that, prebuild so-and-so, switch to version x, or symlink the quizdoodle, etc.
Update:
We tried using dlopen
with RTLD_LOCAL
to isolate the 3rd party library from the rest of our app. This seems to have mostly worked, however, we are left with large memory leaks for unknown reasons. We suspect that, when we call dlopen
, the third party library pulls in symbols like malloc
from the already loaded .so.6, and things get muddled up.
For giggles, we tried putting the third-party library into LD_PRELOAD
, then ran our app, and the memory leaks seems to completely disappear.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以尝试围绕第 3 方库构建一个包装器库:使用该库的静态版本 + 将其与静态标准库链接(-static-libgcc - 确保通过 -L 选择正确的版本)。要做的重要事情是正确关闭此包装器库,即仅应导出原始第 3 方库中的符号,其他所有内容都应隐藏。这样,您的包装库将公开应用程序所需的所有符号,并将标准内容封装在其中。请注意,它不能保证工作,特别是如果您的代码和第 3 方代码之间共享某些内存操作(例如,您在代码中分配内存并在第 3 方中取消分配)...在这种情况下,唯一的选择是保留此第 3 方代码party lib位于不同的进程空间中。
我认为上面提到的动态选项不起作用,因为稍后您会遇到完全相同的问题。
一般来说,最好不要在同一进程空间中混合具有不同运行时的二进制文件。这几乎总是酿成灾难。
You may try to build a wrapper library around your 3rd party library: use the static version of that library + link it with the static standard library (-static-libgcc - make sure you pick up a proper version via -L). The important thing to do is to close this wrapper library properly, i.e only symbols from the original 3rd party library should be exported, everything else should be hidden. This way you wrapper library will expose all needed symbols for your application and encapsulate standard stuff inside. Note it is not guaranteed to work especially if some memory operations are shared between your code and 3rd party code (e.g. you allocate memory in your code and deallocate in 3rd party)... in such case the only option can be to keep this 3rd party lib in a different process space.
I don't think the dynamic option mentioned above would work because you will get exactly same problem - just later.
In general it is better not to mix binaries with different run-times in the same process space. It is almost always a recipe for disaster.
虽然很容易同时将 libstdc++.so.6 和 libstdc++.so.5 链接到您的应用程序,但其行为几乎是未定义的,因为符号基本上是偶然从任一库中获取的。
IMO 成功的最佳方法是在旧系统上围绕您的第 3 方库构建自己的应用程序(使用兼容的 gcc,例如 gcc 3.3),并让它通过 IPC 与您的主应用程序通信(例如共享记忆)。这样,
如果您不想在目标系统上保留 libstdc++.so.5,那么这很简单:使用 gcc 的 -static 标志将 libstdc++.a 链接到您的包装应用程序。
While it is easy to link both libstdc++.so.6 and libstdc++.so.5 to your application at the same time, its behavior will pretty much be undefined, because symbols are taken from either library basically by chance.
Best way to success IMO is to build an own application around your 3rd party lib on an old system (which is using a compatible gcc like, for instance, gcc 3.3), and let it communicate with your main application via IPC (eg. shared memory). This way, no
If you don't want to keep libstdc++.so.5 on your target system, then that's easy: use gcc's -static flag to link libstdc++.a to your wrapper application.
向您的供应商询问该库的较新版本,该库使用的内容并不是非常过时。如果失败,您可以查看新应用程序是否仍然可以与旧版本的库一起使用,并在必要时将其移植回来。尝试拥有同一个库的两个不同版本会带来痛苦,我认为您不会找到可接受的解决方案。
Ask your vendor for a newer version of the library that uses something not horribly out of date. Failing that, you could see if your new application still works with the older version of the library and if necessary port it back. Trying to have two different versions of the same library is asking for pain and I don't think you'll find an acceptable solution.
虽然到目前为止给出的方法之一可能有效,但我认为更安全的说法是您不能直接以可靠的方式做到这一点。如果您使用完全基于 C 的 API(仅与 C 兼容的结构、由 malloc/free 管理的内存等)编写包装器,那么您也许可以使用 pobedim 的解决方案。然而,如果您需要交换 C++ 结构,则并不安全,因为即使您可以实现链接,也会在同一对象上使用不同的标准库实现。此外,C++ ABI 可能在基于 .5 和 .6 的代码库之间不兼容(我不太记得几年前与标准库 soname 相关的主要 Gnu C++ ABI 更改是如何发生的)。
我认为解决这个问题的最安全方法是在应用程序和基于相关库构建的资源/计算服务器进程之间使用多进程方法和某种 IPC。您可以使用 CORBA、D-Bus、Sun RPC 或一些基于管道或套接字的临时协议来完成这项工作。当我尝试在 64 位应用程序中使用闭源 32 位代码时,我已经这样做了,而且效果很好。您将看到性能受到影响,但您也将完全回避尝试在单个进程中混合 C++ 运行时所固有的问题。
While one of the approaches given so far may work, I think it is safer to say that you can't do this directly a reliable fashion. If you write a wrapper using entirely C-based API's (only C-compatible structures, memory managed by malloc/free, etc.), then you might be able to use pobedim's solution. If you need to exchange C++ structures, however, it is not safe as, even if you could make the link happen, different standard libraries implementations would be used on the same objects. Also, the C++ ABI may not be compatible between .5- and .6-based code bases (I don't remember for sure how the major Gnu C++ ABI change happened a few years ago related to standard library sonames).
I think the safest approach to solving this is to use a multiprocess approach with some kind of IPC between your application and a resource/computing server process built on the library in question. You could use CORBA, D-Bus, Sun RPC, or some ad-hoc protocol over pipes or sockets to do the job. I've done this when trying to use closed-source 32-bit code in 64-bit apps, and it works well enough. You will see a performance hit, but you will also completely sidestep the problems inherent in trying to mix C++ runtimes in a single process.