当前位置: 首页 > 面试题库 >

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

简景焕
2023-03-14
问题内容

我需要将基于GCC 4.7的libstdc 的,基于Ubuntu 12.10html" target="_blank">构建的C 应用程序部署到运行Ubuntu
10.04的系统,该系统随附了相当老的libstdc ++版本。

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

我注意到这篇文章是从2005年开始的,此后也许已经发生了很大的变化。它的建议仍然有效吗?我应该注意哪些潜伏问题?


问题答案:

该博客文章非常不准确。

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

不对。自GCC 3.4以来唯一引入的C ABI更改是向后兼容的,这意味着C ABI稳定了将近9年。

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

发行版的GCC补丁版本之间的差异很小,并且不会更改ABI,例如Fedora的4.6.3 20120306(Red Hat 4.6.3-2)与上游FSF
4.6.x版本以及几乎所有4.6都兼容ABI。 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'(请注意使用单引号防止外壳扩展$ORIGIN),则可执行文件将带有RPATH$ORIGIN其告诉动态链接程序在与可执行文件本身相同的目录中查找共享库。如果你把新的libstdc++.so在与可执行文件相同的目录中,它将在运行时找到,问题已解决。(另一种选择是将可执行文件放入其中/some/path/bin/,将较新的libstdc
++。so放入其中,/some/path/lib/并链接'-Wl,-rpath,$ORIGIN/../lib'到可执行文件或相对于可执行文件的任何其他固定位置,并将RPATH设置为$ORIGIN



 类似资料:
  • 问题内容: 我正在编写一个与GNU GPL不兼容的跨平台应用程序。我当前面临的主要问题是该应用程序与glibc和libstdc ++动态链接,并且几乎所有对库的新更新都不向后兼容。因此,在我的应用程序中会看到随机崩溃。 解决方法是,将应用程序的二进制文件分发在几个不同的系统(具有不同的C / C 运行时版本)上编译。但我要没有这个。所以我的问题是,请牢记许可和所有注意事项,我可以静态链接glibc

  • while (<STDIN>) 一定要小心这点。如果你不知怎么回事地得到了假值(如:空行),你的文件可能 停止处理了。假如你在处理文件读取(除非修改了 $/),这种事一般不会发生, 但却可能发生。 你更喜欢这样运行: while (readdir(DIR)) { 假设你有文件名为 0 的话,那么程序将停止,且不会继续处理文件。 更合适的 while 循环看起来像这样: while ( defin

  • 我在Python3中收到了一条SNMP陷阱消息,得到了一个十六进制数。 如何将其转换为字符串以便查看? 接收数据(十六进制) B'0E\x02\x01\x01\x04\x06404040\xa78\x02\x04\x00\xf6\x17~\x02\x01\x00\x02\x01\x000*0\x0f\x06\x08\x06\x01\x02\x01\x01\x03\x00C\x03\x01k0\x1

  • 通常,Python 旨在成为一门简洁一致的语言,避免发生意外。然而,有些情况可能会给新手们造成困惑。 在这些情况中,有一些虽是有意为之,但还是有潜在风险。还有一些则可以说是语言设计缺陷了。总之,下面列出的这些情况都是些乍一看很不好理解的行为,不过一旦您了解了这些奇怪行为背后的机理,也就基本上能理解了。 可变默认参数 似乎每个 Python 新手都会感到惊讶的一点是 Python 在函数定义中对待可

  • 问题内容: 我正在开发一个嵌入式项目,该项目当前在Linux和uClibc中使用C。我们有兴趣将其移至C ,但我不希望与libstdc 中的链接相关的开销。我的印象是,只要我们不使用STL中的任何内容(例如iostream或vector),就可以实现此目的。 如何在不链接libstdc 的情况下引导g 进行编译? 问题答案: 编译时,仅用于编译。然后,使用代替进行链接。但是,这将直接调用链接器,这

  • 静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来 静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库 动态链接方法:使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这