静态库和动态库本质区别在于链接与加载时机:静态库(.a/.lib)在编译链接阶段将代码复制进可执行文件,生成独立程序;动态库(.so/.dll)仅存符号引用,运行时由系统加载共享,节省内存但依赖环境。

静态库和动态库不是“选哪个更好”,而是“在哪用、怎么用”——关键看部署环境、更新频率和资源约束。
静态库(.a)在链接时就把代码塞进可执行文件
链接阶段,ld 把 libxxx.a 中所有被引用的函数代码直接复制进最终的 ./a.out。生成的文件能独立运行,不依赖外部 .so 文件。
- 常见错误:
/usr/bin/ld: cannot find -lxxx—— 没加-L指定路径,或libxxx.a根本不存在 - 必须用
ar rcs libxxx.a xxx.o打包,不能直接拿 .c 或 .o 当库用 -
-static选项会强制所有依赖走静态链接,但若系统没装对应静态库(如libc.a),会直接报错退出 - 生成的可执行文件体积大,但启动快(无运行时加载开销)
动态库(.so)只存符号引用,运行时才加载
编译时只记下“我要调 xxx.so 里的 func”,真正加载发生在程序启动或 dlopen() 调用时。
- 典型错误:
./a.out: error while loading shared libraries: libxxx.so: cannot open shared object file—— 不是编译失败,是运行时找不到.so文件 - 生成时必须加
-fPIC(位置无关代码),否则gcc -shared xxx.o -o libxxx.so会失败 - 运行前要确保
LD_LIBRARY_PATH包含库路径,或把.so放到/usr/lib等系统默认路径并运行sudo ldconfig - 多个进程共享同一份内存中的 .so 实例,节省物理内存
混用时链接顺序和参数很关键
同一个工程里既用静态库又用动态库,gcc 的参数顺序直接影响结果:库必须放在它所满足的依赖之后,且 -lxxx 必须紧挨着它服务的目标文件或源文件。
- 错误写法:
gcc main.o -lxxx -lyyy—— 若main.o依赖libyyy.a,而libxxx.a又依赖libyyy.a,则libyyy.a可能被忽略 - 正确写法:
gcc main.o -lxxx -lyyy或更稳妥地:gcc main.o libxxx.a libyyy.a - 想强制某库走静态链接,用
-Wl,-Bstatic -lxxx -Wl,-Bdynamic包裹,否则gcc默认优先选 .so
最易被忽略的是:动态库的 ABI 兼容性不等于 API 兼容性。哪怕头文件没变,只要 .so 内部结构改了(比如类成员重排、虚表变更),旧程序就可能崩溃——这和静态库“一链永逸”完全不同。











