为啥 g++ 需要 libstdc++.a?为啥不是默认值?
Posted
技术标签:
【中文标题】为啥 g++ 需要 libstdc++.a?为啥不是默认值?【英文标题】:Why does g++ require libstdc++.a? Why is it not the default?为什么 g++ 需要 libstdc++.a?为什么不是默认值? 【发布时间】:2021-01-22 02:34:47 【问题描述】:我有this problem,解决方案是将 libstdc++.a 显式传递给 g++,如下所示:
/usr/local/gcc-10.2.0/bin/g++ -I/usr/local/gcc-10.2.0/include -L/usr/local/gcc-10.2.0/lib64 -Wl,-rpath,/usr/local/gcc-10.2.0/lib64 b.cpp /usr/local/gcc-10.2.0/lib64/libstdc++.a
我的问题:为什么我需要显式传递 libstdc++.a?我怎样才能让它自动化,以便默认使用 libstdc++.a?我怎样才能找到这两个问题的答案?
测试代码:
#include <sstream>
using namespace std;
int
main ()
ostringstream oss;
unsigned long k = 5;
oss << k;
使用以下参数编译:
/usr/local/gcc-10.2.0/bin/g++ -I/usr/local/gcc-10.2.0/include -L/usr/local/gcc-10.2.0/lib64 -Wl,-rpath,/usr/local/gcc-10.2.0/lib64 -lstdc++ b.cpp
得到以下输出:
/tmp/cclRSXGV.o: In function main': b.cpp:(.text+0x35): undefined reference to std::ostream::operator<<(unsigned long)'
collect2: error: ld returned 1 exit status
使用 GNU gcc 10.2.0,安装如下:
../gcc-10.2.0/configure --prefix=/usr/local/gcc-10.2.0 --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++ --disable-dssi --enable-libgcj-multifile --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux && make install-strip
GNU gcc 4.4.7 默认安装在 /usr,GNU gcc 9.2.0 安装在 /usr/local/gcc-9.2.0
运行 /usr/local/gcc-10.2.0/bin/g++ -v b.cpp
会产生以下结果:
Using built-in specs.
COLLECT_GCC=/usr/local/gcc-10.2.0/bin/g++
COLLECT_LTO_WRAPPER=/usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/10.2.0/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../gcc-10.2.0/configure --prefix=/usr/local/gcc-10.2.0 --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++ --disable-dssi --enable-libgcj-multifile --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (GCC)
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
/usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/10.2.0/cc1plus -quiet -v -D_GNU_SOURCE b.cpp -quiet -dumpbase b.cpp -mtune=generic -march=x86-64 -auxbase b -version -o /tmp/ccJiMH6j.s
GNU C++14 (GCC) version 10.2.0 (x86_64-redhat-linux)
compiled by GNU C version 10.2.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.18-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../../../include/c++/10.2.0
/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../../../include/c++/10.2.0/x86_64-redhat-linux
/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../../../include/c++/10.2.0/backward
/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/include
/usr/local/include
/usr/local/gcc-10.2.0/include
/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/include-fixed
/usr/include
End of search list.
GNU C++14 (GCC) version 10.2.0 (x86_64-redhat-linux)
compiled by GNU C version 10.2.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.18-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 410dfe626634fcd13dbcedee05209c5e
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
as -v --64 -o /tmp/ccUyoUr2.o /tmp/ccJiMH6j.s
GNU assembler version 2.35 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.35
COMPILER_PATH=/usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/10.2.0/:/usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/10.2.0/:/usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/:/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/:/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/:/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
/usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/10.2.0/collect2 -plugin /usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/10.2.0/liblto_plugin.so -plugin-opt=/usr/local/gcc-10.2.0/libexec/gcc/x86_64-redhat-linux/10.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccfGN6NK.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/../lib64/crt1.o /usr/lib/../lib64/crti.o /usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/crtbegin.o -L/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0 -L/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/../../.. /tmp/ccUyoUr2.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/crtend.o /usr/lib/../lib64/crtn.o
/usr/local/bin/ld: /tmp/ccUyoUr2.o: in function `main':
b.cpp:(.text+0xc9): undefined reference to `std::cout'
/usr/local/bin/ld: b.cpp:(.text+0x35): undefined reference to std::ostream::operator<<(unsigned long)'
collect2: error: ld returned 1 exit status
【问题讨论】:
g++支持多种标准库,甚至交叉编译等。这些需要指定要链接的自定义标准库。我不知道如何让 g++ 默认使用特定的,所以我会让其他人回答这个问题。 对于正确配置的编译器,您应该不需要这些-I
、-L
或 -l
标志。您可能需要的唯一一个是-Wl,-rpath
。运行/usr/local/gcc-10.2.0/bin/g++ -v b.cpp
并发布输出。
@n.'pronouns'm。我已经发布了使用-v
编译的输出...您认为可能有什么问题?
/usr/local/gcc-10.2.0/lib/gcc/x86_64-redhat-linux/10.2.0/
或/usr/local/gcc-10.2.0/lib64/
中是否有任何名为 libstdc++.so.6 的文件?它包含什么?
libstdc++.a 和 libstdc++.so 都在 /usr/local/gcc-10.2.0/lib64 中。这就是为什么当我用 /usr/local/gcc-10.2 调用 g++ 时它起作用的原因.0/lib64/libstdc++.a
【参考方案1】:
默认情况下,g++ 链接到动态 libstdc++ 库 (libstdc++.so)。通过显式传递 libstdc++.a ,您将链接到静态对应项。您可以使用-static-libstdc++
获得相同的最终结果。
针对 libstdc++ 的静态和动态链接都应该有效。您的问题可能是由错误地构建或安装 GCC 引起的(例如,应用了不正确的补丁,或者混合了来自不同 GCC 构建的包含文件)。
要进行调查,通过将 -c
添加到 g++ 命令行来生成目标文件 b.o
,并通过添加 -E -o b.ii
来预处理源文件 b.ii
。使用nm -u b.o
获取未定义符号的错位名称(将-C
添加到demangle)。您会看到缺失符号的错位名称是_ZNSolsEm
。尝试在 libstdc++ (nm -D --defined-only /usr/local/gcc-10.2.0/lib64/libstdc++.so
) 定义的符号列表中查找缺失的符号。如果库中缺少它,问题是包含的文件希望库提供这些模板实例化,而实际库没有。
如果你查看b.ii
,你会发现它在末尾声明了对应的extern template
:
extern template class basic_ostringstream<char>;
如果您查看来自此行的 gcc 安装树中的 sstream.tcc
文件,您会看到它由 #if _GLIBCXX_EXTERN_TEMPLATE
保护。该宏的定义在c++config.h
中,并根据libstdc++ 配置时的--enable-extern-template
选项进行设置。如果库是用--disable-extern-template
构建的,它不会提供那些模板实例化。
【讨论】:
以上是关于为啥 g++ 需要 libstdc++.a?为啥不是默认值?的主要内容,如果未能解决你的问题,请参考以下文章
安装oracle 11g,为啥不需要windows系统安装jre就可以安装?
为啥 g++ 不关心初始化列表分配给 (const std::string&) a (std::string)?和其他怪异[关闭]
为啥我需要在 g++ 中使用 typedef typename 而不是 VS?