静态库

本文详细介绍了静态库的概念、优缺点及其在Linux环境下的创建与使用流程。通过具体实例展示了如何利用AR工具创建静态库,并解释了链接器如何解析静态库中的引用。
  • 静态库:
    实际上所有的编译器都提供一种机制,将所有的相关的目标模块打包成为一个单独的文件。这个文件称为静态库。
    静态库可以用作链接器的输入,当链接器构造一个输出的可执行文件时,它只拷贝静态库到被应用程序引用的目标模块。
    在编译完成之后,静态库可以被抛弃掉。
  • 优点:
    可以对文件进行打包。
    运行速度较快。
    较相对安全。
    将编译器的实现与标准函数的实现分离开来,并且仍然对程序员保持适度的便利。
  • 缺点:
    可能造成生成的目标文件过大。
    每个可执行文件都包含着一份引用函数集合的完全拷贝,这对磁盘空间是很浪费的。
    如果静态库被修改,则目标文件需要重新进行编译。(更加耗时)

在 linux 中,我们使用 AR 工具进行静态库的创建
在这里我们首先写一个简单的加减乘的函数
这里写图片描述
然后通过 main.c 文件调用其中的加法和乘法
这里写图片描述
此时对 main.c 进行编译是无法通过的
这里写图片描述
现在我们打包出一个静态库
这里写图片描述
此时可以发现,本地文件中出现了一个 libmymath.a 的静态库文件
这里写图片描述
通过查看可以发现,相应的 .o 文件已经打包在了动态库文件中。
我们将 main.c 与 libmymath.a 一起进行编译

gcc test.c -I include -L lib -lmymath
         //-I + 头文件路径  -L + 库文件路径 -l + 静态库名

这里写图片描述
此时发现程序可以正常运行了
这里写图片描述
通过对可执行文件的查看,我们可以发现只插入了 add mul 的函数,而没有插入 sub ,所以只插入需要的内容。
这里写图片描述
此时就算我们将静态库文件移除,程序依然可以进行,因为相应的程序代码已经装进了代码段。
这里写图片描述
但是如果我们将第一次对 main.c 进行编译的时候,就需要加上库文件路径 -L +
如果没有自己手动加上路径,系统会先在 /lib /lib64 . 文件中寻找相应的静态库文件
如果没有找到则报错。 所以我们也可以将自己打包的静态库文件放到 /lib 或 /lib64 中。

现在整个工作过程已经熟悉了,我们来了解连接器是如何使用静态库来解析引用的。

在符号解析的阶段,链接器从左到右按照他们在编译器驱动程序命令行上出现的顺序来扫描可可重定位文件和存档文件。
在这次扫描中,连接器维持一个可重定位目标文件的集合 E,一个未解析符号集合 U,一个在前面输入文件已定义的符号集合 D。初始 E,U,D都为空。

  • 对于命令行上的每个输入文件 f ,链接器会判断 f 是一个目标文件还是一个存档文件,如果是一个目标文件,那么链接器把 f 添加到 E 中,修改 U 和 D 来反映 f 的符号定义和引用,并继续读取下一个输入文件。
  • 如果 f 是一个存档文件,那么链接器就尝试匹配 U 中未解析的符号和由存档文件成员定义的符号。如果某个存档文件成员 m,定义了一个符号来解析 U 中的一个引用,那么就将 m 加到 E 中,并且链接器修改 U 和 D 来反映 m 中的符号定义和引用。对存档文件所有成员目标文件都反复进行这个过程,直到 U 和 D 不再繁盛变化。
  • 如果当链接器完成对命令行上输入文件的扫描后,U 是非空的,那么链接器就会输出一个错误并终止。否则它会合并重定位 E 中的目标文件,从而构建输出的可执行文件。

注意:命令行上的库和目标文件的顺序非常重要,如果定义一个符号的库出现在引用这个符号的目标文件之前,那么引用就不能被解析,链接会失败。并且如果库不是相互独立的,那么他们同样必须排序。如果需要满足依赖需求,可以在命令行上重复库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值