Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
链接libstdc&x2B+;静态:有什么问题吗? 我需要在Ubuntu 12.10上构建一个C++应用程序,其中GCC 4.7的LIbSTDC++可以运行到运行Ubuntu 10.04的系统,它带有一个相当旧的版本的LBSTDC++._C++_Linux_Gcc_Static Libraries_Libstdc++ - Fatal编程技术网

链接libstdc&x2B+;静态:有什么问题吗? 我需要在Ubuntu 12.10上构建一个C++应用程序,其中GCC 4.7的LIbSTDC++可以运行到运行Ubuntu 10.04的系统,它带有一个相当旧的版本的LBSTDC++.

链接libstdc&x2B+;静态:有什么问题吗? 我需要在Ubuntu 12.10上构建一个C++应用程序,其中GCC 4.7的LIbSTDC++可以运行到运行Ubuntu 10.04的系统,它带有一个相当旧的版本的LBSTDC++.,c++,linux,gcc,static-libraries,libstdc++,C++,Linux,Gcc,Static Libraries,Libstdc++,目前,我正在使用-static libstdc++-static libgcc进行编译,正如本文所建议的那样:。作者警告不要在编译ListSTDC++时使用任何动态加载的C++代码,这是我还没有检查过的。不过,到目前为止,一切似乎都进展顺利:我可以利用Ubuntu 10.04上的C++11功能,这正是我所追求的 我注意到这篇文章是从2005年开始的,从那以后可能有了很大的变化。它的建议仍然有效吗?是否有任何我应该注意的潜在问题?您可能还需要确保不依赖动态glibc。在生成的可执行文件上运行ldd

目前,我正在使用
-static libstdc++-static libgcc
进行编译,正如本文所建议的那样:。作者警告不要在编译ListSTDC++时使用任何动态加载的C++代码,这是我还没有检查过的。不过,到目前为止,一切似乎都进展顺利:我可以利用Ubuntu 10.04上的C++11功能,这正是我所追求的


我注意到这篇文章是从2005年开始的,从那以后可能有了很大的变化。它的建议仍然有效吗?是否有任何我应该注意的潜在问题?

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


另外一个练习是使用此方法构建一组相关的C++11示例,并在真实的10.04系统上实际尝试生成的二进制文件。在大多数情况下,除非你对动态加载做了一些奇怪的事情,否则你会马上知道程序是工作还是崩溃。

那篇博文是非常不准确的

据我所知,C++的ABI变化已经被引入了GCC的每个主要版本(即那些具有不同的第一或第二版本号成分)。 不是真的。由于GCC 3.4已经向后兼容,所以C++的ABI变化是唯一的,这意味着C++ ABI已经稳定了将近九年。 更糟糕的是,大多数主要的Linux发行版都使用GCC快照和/或修补其GCC版本,这使得在分发二进制文件时,几乎不可能确切知道您可能要处理的GCC版本

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

在GNU/Linux上,GCC的运行时库使用ELF符号版本控制,因此很容易检查对象和库所需的符号版本,如果您有
libstdc++,那么提供这些符号的
将起作用,它是否与发行版的另一个版本略有不同并不重要

<>但是,如果要工作,则没有C++代码(或者任何C++运行时支持的代码)可以动态链接。 这也不是事实

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

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


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

乔纳森·韦克利(Jonathan Wakely)的优秀答案中还有一个补充,即为什么dlopen()有问题:


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

我想补充乔纳森·韦克利的回答如下

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

摘要:如果应用程序加载/卸载pl
App.exe (RPATH=.:./gcc4_9/libstdc++.so.x)
Dependency.so (RPATH=.:./gcc5_5/libstdc++.so.y)