该博客文章非常不准确。
据我所知,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
)
-static-libstdc++
选择没有意义,那么您只需使用-static