我试图了解 g++ 如何选择它链接的 libstdc++ 版本,以及当库的“系统”版本不同时这意味着什么。
我正在使用 gcc/g++ 4.1.2,根据 ABI 指南 文档,它包含 libstdc++.so.6.0.8,果然:
-rwxr-xr-x 1 root root 4397810 May 18 2007 /opt/gcc4.1.2/lib/libstdc++.so.6.0.8
根据我对 ABI 前向兼容性的理解,我可以使用 g++ 4.1.2 进行构建,并期望代码可以在 libstdc++ 版本高于 6.0.8 的系统上运行,但不能在较早版本的系统上运行,因为将会有旧版本的 ABI。
在同一台机器上 /usr/lib 中有旧版本的 libstdc++:
-rwxr-xr-x 1 root root 804288 Jul 22 2005 /usr/lib/libstdc++.so.6.0.3
如果我在本机上使用 g++ 4.1.2 编译代码,然后 ldd 它,我会在 /usr/lib 中看到引用的 libstdc++ 版本,即 6.0.3:
# ldd test
.
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x005b6000)
.
这是预期的,因为首先检查 /usr/lib。并且应用程序运行良好。
我的问题是:这里发生了什么?
g++ 4.1.2 是否与作为该版本 (6.0.8) 一部分的 libstdc++.so 版本链接?如果是这样,当可执行文件具有较旧的 ABI 时,为什么可执行文件可以在运行时使用 /usr/lib 中的旧版本?运气好?
或者 g++ 4.1.2 在链接时选择了 /usr/lib 版本的 libstdc++ (6.0.3) 并使用它,因为它以与运行时可执行文件相同的方式解析库路径?即使 libstdc++ 不是它“自己的”版本,g++ 可以做到这一点吗? g++4.1.2 (6.0.8) 中 libstdc++ 版本的用途是什么?在此过程中是否使用过它?
任何见解表示赞赏。
GCC 根据目录搜索列表选择所有库。你可以这样看:
gcc -print-search-dirs
该列表通常更喜欢特定于编译器版本的库(如果有的话)。
但是,链接时选择可能与运行时选择不同。
如果链接器命令包含
-rpath
选项(某些工具链供应商可能包含非标准选项),则动态链接器将使用该选项在运行时查找正确的库。否则系统将使用其默认库。
如果两个库不匹配,那么可能会发生不好的事情。 C 库(通常是 glibc)一直很小心地维护兼容性。 C++ 库并不总是有这种奢侈。近年来它更加安全,但许多人仍然建议不混合搭配。
默认情况下,gcc 使用 /usr/lib 路径中的库。
1. gcc/g++ 4.1.2 未链接到最新版本的 libstdc++.so.6.0.8。
2. g++ 4.1.2 在链接时选择了 /usr/lib 版本的 libstdc++ (6.0.3)。
它仍然使用系统默认的libstdc++.so.6.0.3,除非你明确设置库路径。
对于gcc/g++ 4.1.2,要使用最新版本的libstdc++.so.6.0.8,需要在编译前导出库路径。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/gcc4.1.2/lib
现在使用 gcc/g++ 4.1.2 链接时,将使用 libstdc++.so.6.0.8。