静态链接 libstdc++:有什么陷阱吗?

2024-10-24 08:51:00
admin
原创
294
摘要:问题描述:我需要将在 Ubuntu 12.10 上使用 GCC 4.7 的 libstdc++ 构建的 C++ 应用程序部署到运行 Ubuntu 10.04 的系统上,该系统附带了相当旧版本的 libstdc++。目前,我正在使用 进行编译-static-libstdc++ -static-libgcc,正如...

问题描述:

我需要将在 Ubuntu 12.10 上使用 GCC 4.7 的 libstdc++ 构建的 C++ 应用程序部署到运行 Ubuntu 10.04 的系统上,该系统附带了相当旧版本的 libstdc++。

目前,我正在使用 进行编译-static-libstdc++ -static-libgcc,正如这篇博客文章所建议的那样:静态链接 libstdc++。作者警告在静态编译 libstdc++ 时不要使用任何动态加载的 C++ 代码,这是我尚未检查的内容。不过,到目前为止一切似乎都很顺利:我可以在 Ubuntu 10.04 上使用 C++11 功能,这正是我想要的。

我注意到这篇文章是 2005 年的,从那时起可能已经发生了很多变化。它的建议仍然适用吗?有什么潜在问题我应该注意吗?


解决方案 1:

那篇博客文章相当不准确。

据我所知,GCC 的每个主要版本都引入了 C++ ABI 变化(即具有不同第一个或第二个版本号组件的版本)。

不对。自 GCC 3.4 以来引入的唯一 C++ ABI 变化是向后兼容的,这意味着 C++ ABI 已经稳定了近九年。

更糟糕的是,大多数主流 Linux 发行版都使用 GCC 快照和/或修补其 GCC 版本,因此几乎不可能在分发二进制文件时确切知道您可能正在处理的 GCC 版本。

发行版的 GCC 修补版本之间的差异很小,并且 ABI 没有变化,例如 Fedora 的 4.6.3 20120306(Red Hat 4.6.3-2)与上游 FSF 4.6.x 版本是 ABI 兼容的,并且几乎可以肯定与任何其他发行版的 4.6.x 兼容。

在 GNU/Linux 上,GCC 的运行时库使用 ELF 符号版本控制,因此很容易检查对象和库所需的符号版本,如果您有一个libstdc++.so提供这些符号的版本,它就会起作用,即使它与您的发行版的另一个版本略有不同,修补版本也没有关系。

但如果要使其工作,则不能动态链接任何 C++ 代码(或任何使用 C++ 运行时支持的代码)。

这也不是事实。

也就是说,静态链接libstdc++.a是您的一个选择。

如果您动态加载库(使用dlopen),则可能无法正常工作的原因是,当您(静态)链接它时,您的应用程序可能不需要它所依赖的 libstdc++ 符号,因此这些符号将不会出现在您的可执行文件中。可以通过将共享库动态链接到libstdc++.so(如果它依赖于它,这无论如何都是正确的做法)来解决此问题。ELF 符号插入意味着可执行文件中存在的符号将被共享库使用,但可执行文件中不存在的其他符号将在libstdc++.so它链接到的任何地方找到。如果您的应用程序不使用,dlopen您无需关心这一点。

另一个选项(也是我更喜欢的选项)是将较新的版本libstdc++.so与您的应用程序一起部署,并确保在默认系统之前找到它libstdc++.so,这可以通过强制动态链接器在正确的位置查找来完成,可以在$LD_LIBRARY_PATH运行时使用环境变量,也可以RPATH在链接时在可执行文件中设置。我更喜欢使用,RPATH因为它不依赖于正确设置的环境来使应用程序工作。如果您将应用程序链接到'-Wl,-rpath,$ORIGIN'(请注意单引号以防止 shell 尝试扩展$ORIGIN),则可执行文件将具有一个RPATH$ORIGIN它告诉动态链接器在与可执行文件本身相同的目录中查找共享库。如果将较新的版本放在与libstdc++.so可执行文件相同的目录中,它将在运行时被发现,问题解决了。(另一个选择是将可执行文件放在中,/some/path/bin/将较新的 libstdc++.so 放在中/some/path/lib/并链接到'-Wl,-rpath,$ORIGIN/../lib'或任何其他相对于可执行文件的固定位置,并设置相对于的 RPATH $ORIGIN

解决方案 2:

除了 Jonathan Wakely 的出色回答之外,还有一个问题,为什么 dlopen() 是有问题的:

由于 GCC 5 中新增了异常处理池(请参阅PR 64535和PR 65434),如果您 dlopen 和 dlclose 静态链接到 libstdc++ 的库,每次都会发生内存泄漏(池对象)。因此,如果您有机会使用 dlopen,静态链接 libstdc++ 似乎是一个非常糟糕的主意。请注意,这是一个真正的泄漏,而不是PR 65434中提到的良性泄漏。

解决方案 3:

Jonathan Wakely 关于 RPATH 的回答补充:

只有当所讨论的 RPATH 是正在运行的应用程序的 RPATH 时,RPATH 才会起作用。如果您有一个库,它通过自己的 RPATH 动态链接到任何库,则该库的 RPATH 将被加载它的应用程序的 RPATH 覆盖。当您无法保证应用程序的 RPATH 与库的 RPATH 相同时,就会出现问题,例如,如果您希望依赖项位于特定目录中,但该目录不是应用程序的 RPATH 的一部分。

例如,假设您有一个应用程序 App.exe,它对 GCC 4.9 的 libstdc++.so.x 具有动态链接依赖关系。App.exe 通过 RPATH 解析了此依赖关系,即

App.exe (RPATH=.:./gcc4_9/libstdc++.so.x)

现在假设有另一个库 Dependency.so,它对 GCC 5.5 的 libstdc++.so.y 有动态链接依赖。这里的依赖关系通过库的 RPATH 来解析,即

Dependency.so (RPATH=.:./gcc5_5/libstdc++.so.y)

当 App.exe 加载 Dependency.so 时,它既不附加也不添加库的 RPATH。它根本不会参考它。唯一要考虑的 RPATH 是正在运行的应用程序的 RPATH,在本例中是 App.exe 的 RPATH。这意味着,如果库依赖于 gcc5_5/libstdc++.so.y 中但不在 gcc4_9/libstdc++.so.x 中的符号,则库将无法加载。

这只是一个警告,因为我以前也遇到过这些问题。RPATH 是一个非常有用的工具,但它的实现仍然存在一些问题。

解决方案 4:

您可能还需要确保不依赖动态 glibc。运行ldd生成的可执行文件并注意任何动态依赖项(libc/libm/libpthread 通常是可疑的)。

额外的练习是使用此方法构建一堆复杂的 C++11 示例,并在真正的 10.04 系统上实际尝试生成的二进制文件。在大多数情况下,除非您对动态加载做了一些奇怪的事情,否则您会立即知道程序是正常运行还是崩溃。

解决方案 5:

我想对 Jonathan Wakely 的回答进行以下补充。

在 Linux 上玩的时候-static-libstdc++,我遇到了 的问题dlclose()。假设我们有一个应用程序“A”静态链接到libstdc++,并且它在运行时动态加载链接到libstdc++插件“P”。这很好。但是当“A”卸载“P”时,会发生分段错误。我的假设是卸载后libstdc++.so,“A”不再可以使用与 相关的符号libstdc++。请注意,如果“A”和“P”都静态链接到libstdc++,或者“A”动态链接而“P”静态链接,则不会发生问题。

摘要:如果您的应用程序加载/卸载可能动态链接到的插件libstdc++,则应用程序也必须动态链接到它。这只是我的观察,我希望得到您的评论。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2593  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1555  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   32  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   28  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   24  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用