g++默认动态链接libstdc++和libgcc,目标机缺失对应so文件会报错;必须加-static-libstdc++和-static-libgcc实现静态链接,交叉编译还需匹配工具链、sysroot与ABI。

g++ 默认链接的是动态 libstdc++,目标机缺库就报错
直接用 g++ main.cpp -o app 编译出来的程序,在没装 GCC 运行时库的目标机上运行,大概率会卡在 error while loading shared libraries: libstdc++.so.6: cannot open shared object file。这不是你的程序坏了,是它默认依赖宿主机上的 libstdc++.so.6 动态库,而目标机根本没这个文件,也没 ldconfig 管理路径。
用 -static-libstdc++ 和 -static-libgcc 强制静态链接 C++ 运行时
这两个参数才是关键开关,不是可选,是必须加:
-
-static-libstdc++:把libstdc++打进可执行文件,不再找动态.so -
-static-libgcc:同理,解决libgcc_s.so.1缺失问题(尤其涉及异常、RTTI 时必现) - 注意:它们只静态链接 GCC 自家的运行时,不触碰你自己的
.a或系统其他库(如libc)
正确写法示例:g++ main.cpp -o app -static-libstdc++ -static-libgcc
编译后用 ldd app 检查:如果输出里不再出现 libstdc++.so.6 或 libgcc_s.so.1,说明生效了。
目标机连 libc 都没有?那就得全静态链接 -static
某些极简嵌入式环境(比如裸 BusyBox、musl 系统、或容器精简镜像),连 libc 都不提供动态版本。这时 -static-libstdc++ 不够用,必须上 -static:
立即学习“C++免费学习笔记(深入)”;
-
-static会让g++强制所有依赖(包括libc、libm、libpthread等)都打成静态,生成纯二进制 - 副作用明显:体积暴涨(几 MB 起步),且失去
fork/exec等部分高级功能(musl 下更敏感) - 验证方式:
file app应显示statically linked;ldd app会直接报not a dynamic executable
命令示例:g++ main.cpp -o app -static
交叉编译时别漏掉 sysroot 和 target ABI 匹配
如果你是在 x86_64 宿主机上为 ARM 板编译,光加静态参数没用——工具链本身得对得上:
- 确保用的是目标平台的交叉工具链,比如
arm-linux-gnueabihf-g++,不是本机g++ - 确认
--sysroot指向的是目标机的根文件系统(含头文件和静态库),否则-static-libstdc++会找不到对应版本的libstdc++.a - ABI 必须一致:例如
gnueabihf工具链不能去链接gnueabi的库,readelf -A app可查 ABI tag
典型交叉静态编译命令:arm-linux-gnueabihf-g++ main.cpp -o app --sysroot=/path/to/sysroot -static-libstdc++ -static-libgcc
真正容易被忽略的点是:静态链接不是“加个 flag 就完事”,它要求工具链、sysroot、目标机 ABI 三者严丝合缝。少一个,libstdc++.a 找不到,或者链接出错,或者运行时崩溃——这些都不会在编译阶段报错,而是在目标机上静默失败。


















