我需要部署建立在Ubuntu 12.10与GCC 4.7的的libstdc ++来运行Ubuntu 10.04,它带有一个相当旧版本的libstdc ++系统C ++应用程序。
目前,我与编译-static-libstdc++ -static-libgcc
,所建议的这个博客帖子: 链接的libstdc ++静态 。 作者警告说,不要编制的libstdc ++静态时使用任何动态加载的C ++代码,这是我还没有检查。 不过,一切似乎顺利,到目前为止是想:我可以使用C ++ 11层的功能在Ubuntu 10.04,这是我后。
我注意到,这篇文章是从2005年,从那时起,也许多大变化。 是它的建议仍然是当前? 是否有任何问题,潜伏着我应该知道的?
该博客文章是相当不准确的。
据我了解C ++ ABI的变化已经推出了GCC的每一个主要版本(即具有不同的第一或第二版本号的组件)。
不对。 由于GCC 3.4中引入的唯一的C ++ ABI变化是向后兼容的,这意味着C ++ ABI已经稳定了将近九年。
更糟糕的是,大多数主要的Linux发行版使用GCC快照和/或修补他们版本的GCC,使得它几乎不可能确切地知道什么版本的GCC,你可能会打交道时,你分发的二进制文件。
分布GCC的修补的版本之间的差异是轻微的,并且不会改变ABI,例如Fedora的4.6.3 20120306(红帽4.6.3-2)是ABI与上游FSF 4.6.X版本兼容,几乎可以肯定与任何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 ++。所以在/some/path/lib/
下,然后链接'-Wl,-rpath,$ORIGIN/../lib'
或任何其它固定位置相对于所述的可执行文件,并相对于设置RPATH $ORIGIN
)
其中除了乔纳森Wakely的出色答卷,为什么dlopen的()是有问题的:
由于GCC 5新的异常处理池(见PR 64535和PR 65434 ),如果您使用dlopen和dlclose静态链接与libstdc ++库,你会得到一个内存泄漏(池对象的)各一次。 所以,如果有任何机会,你会永远使用dlopen的,这似乎是一个非常糟糕的主意静态链接的libstdc ++。 请注意,这是相对于中提到的良性一个真正的泄漏PR 65434 。
您可能还需要确保你不依赖于动态的glibc。 运行ldd
您生成的可执行文件,并注意任何动态依赖关系(的libc / libm中/的libpthread是USAL嫌疑人)。
附加练习将建立一堆使用这种方法涉及C ++ 11个的例子,实际上想一个真正的10.04系统上所产生的二进制文件。 在大多数情况下,除非你做一些奇怪的动态加载,你马上就会知道该系统是否正常工作或崩溃。
我想补充乔纳森Wakely的回答如下。
各地播放-static-libstdc++
在Linux上,我所面临问题与dlclose()
假设我们有一个应用程序“A”静态链接到libstdc++
和它加载动态链接到libstdc++
插件在运行时“P”。 没关系。 但是,“A”卸载“P”时,发生分段故障。 我的假设是,卸载后libstdc++.so
,“A”不再可以使用相关的符号libstdc++
。 请注意,如果两个“A”和“P”静态链接到libstdc++
,或者如果“A”被动态链接和“P”静态,不会发生该问题。
摘要:如果你的应用程序加载/卸载的插件,可以动态链接到libstdc++
,应用程序也必须动态链接到它。 这只是我的观察,我想获得您的宝贵意见。