静态库libxxx.a是归档的.o文件,链接时复制代码进可执行文件,运行不依赖外部库但体积大;动态库libxxx.so运行时加载,共享且易更新但需环境支持;链接顺序、路径配置和符号检查是关键。

静态库 libxxx.a 是怎么被链接进程序的
它本质是一堆已编译好的 .o 文件打包而成的归档,链接时把用到的目标代码直接复制进最终可执行文件。这意味着运行时不依赖外部库文件,但体积变大、更新需重编译。
常见错误现象:undefined reference to 'xxx' —— 很可能是因为没加 -lxxx 或没指定 -L/path/to/lib,或者函数符号在 .a 里根本没被定义(比如只声明没实现,或被 static 修饰了)。
实操建议:
- 用
ar -t libxxx.a查看里面包含哪些.o文件 - 用
nm -C libxxx.a | grep 'your_func'确认符号是否存在且未被 strip - 链接顺序很重要:依赖别人的库要放在被依赖库之后,比如
g++ main.o -lA -lB,若A依赖B,这个顺序不能反
动态库 libxxx.so 的加载时机和路径问题
它不参与编译期链接,只在运行时由动态链接器 ld-linux.so 加载。好处是多个程序共享一份代码、升级方便;坏处是运行环境必须有对应版本,否则直接报错。
立即学习“C++免费学习笔记(深入)”;
典型错误:error while loading shared libraries: libxxx.so: cannot open shared object file: No such file or directory —— 不是编译失败,而是运行时找不到。
实操建议:
- 编译时加
-Wl,-rpath,'$ORIGIN'让程序优先从自身所在目录找.so - 临时生效用
LD_LIBRARY_PATH=/path/to/so ./myapp,但别在生产环境长期依赖它 - 系统级安装后记得跑
sudo ldconfig更新缓存,否则/usr/local/lib下的库可能仍不可见
g++ 链接时 -lxxx 找不到 .a 或 .so 怎么办
编译器默认按 .so → .a 顺序查找,如果同名两者都存在,会优先选动态库。想强制用静态库,得加 -static-libxxx 或整个静态链接 -static(慎用,glibc 不支持全静态)。
容易踩的坑:
-
-lxxx中的xxx对应的是库名,不是文件名:比如libjsoncpp.a要写成-ljsoncpp,不是-ljsoncpp.a -
pkg-config --libs xxx返回的可能是带-L和-l的完整字符串,直接粘贴进命令行就行,别手动拆 - 交叉编译时,宿主机的
/usr/lib下的.so不能直接用,必须用目标平台的工具链提供的库
怎么判断一个可执行文件用了哪些动态库
用 ldd ./myapp 最直接,但它只是模拟加载过程,结果未必等于真实运行行为(比如某些库在 dlopen 后才加载)。
更准的方式是运行时看 /proc/PID/maps 或用 strace ./myapp 2>&1 | grep openat 观察实际打开的文件。
注意点:
-
ldd显示not found不代表一定失败——如果代码里用dlopen("xxx.so", RTLD_LAZY)且没调用相关函数,程序照样能启动 -
objdump -p ./myapp | grep NEEDED可看到编译时声明依赖的库列表,比ldd更“静态” - 用
readelf -d ./myapp | grep RUNPATH能确认-rpath是否生效
libA.so.1,而某个第三方 .so 内部硬编码依赖 libA.so.2 —— 这种问题 runtime 才暴露,且很难从编译日志发现。











