为何共享库引用静态库时,静态库未使用对象会被纳入最终二进制文件?
静态库与共享库交叉调用的“隐形大坑”
嘿,踩过静态库和共享库联动的坑吗?我最近碰到一个特别反直觉的情况——静态库的所有对象文件(哪怕完全没被业务逻辑用到)都会被打包进最终的二进制文件里! 是不是有点懵?别急,我给你慢慢拆解,还准备了极简可复现的示例哦~
先说说正常情况是啥样的
原本的常规场景是这样:我们有一个二进制文件
main,它调用静态库libsub.a里的fun1a(),同时main自身还有个内部函数mainsub()。静态库libsub.a里包含好几个对象文件,每个文件里又有多个对外暴露的函数。按照正常逻辑,编译main之后,生成的二进制文件应该只包含静态库中被实际用到的对象文件的副本,对吧?
触发“大坑”的特殊场景
但一旦出现静态库和共享库之间的交叉调用,情况就彻底变了!举个例子:如果静态库libsub.a里某个未被main直接调用的对象文件,里面的函数调用了某个共享库的函数;反过来,这个共享库又调用了静态库的其他函数——这时候链接器就会“一股脑”把整个静态库的所有对象文件都拉进最终的二进制里,哪怕这些对象完全没被main或者业务逻辑用到!
极简可复现示例(SSCCE)
我准备了一套能直接编译运行的代码,帮你快速复现这个问题:
1. 编写所有源码文件
- sub1.c(静态库中被
main直接调用的对象)
#include <stdio.h> void fun1a() { printf("This is fun1a from libsub.a\n"); }
- sub2.c(静态库中未被
main调用,但调用共享库的对象)
#include "shared.h" void fun2a() { // 调用共享库函数 shared_func(); }
- shared.c(共享库源码,反向调用静态库函数)
#include "shared.h" #include "sub.h" void shared_func() { // 调用静态库的fun1a fun1a(); }
- main.c(主程序)
#include "sub.h" void mainsub() { printf("This is internal mainsub\n"); } int main() { fun1a(); mainsub(); return 0; }
- 配套头文件
sub.h:
void fun1a(); void fun2a();
shared.h:
void shared_func();
2. 编译构建命令
# 编译静态库的对象文件并打包 gcc -c sub1.c sub2.c ar rcs libsub.a sub1.o sub2.o # 编译生成共享库 gcc -fPIC -shared shared.c -o libshared.so # 编译主程序并链接库文件 gcc main.c -L. -lsub -lshared -o main
3. 验证问题
用nm命令查看main的符号表,你会发现fun2a这个完全没被main调用的函数竟然出现在里面——这就说明sub2.o整个被打包进最终二进制了!
内容的提问来源于stack exchange,提问作者NoobInside
相关产品推荐
相关产品推荐

