静态库详解

静态库

1 命名规则

lib+name+.a,例如:libtest.a

2 制作过程

其实静态库就是由很多生成的.o文件打包到一起得到的一个.a文件,所以制作过程主要有三大步。我们举一个简单的例子来说明,比如我现在要实现一个算法库,该库只实现简单的加减乘除4个功能。

  1. 准备原材料:
    首先需要编写好必要的源文件以及头文件,我们把头文件放到include目录,源文件放到src目录,即将生成的库文件放到lib目录中,由于例子比较简单这里不列出源代码的内容了,重点看一下过程。
    在这里插入图片描述

  2. 生成对应的.o文件:
    这里我们使用-c选项。
    在这里插入图片描述

  3. 将生成的.o文件打包:
    使用ar命令:ar rcs + 静态库名子 + 生成的所有的.o
    在这里插入图片描述
    这样我们就制作好了一个静态库。

3 发布和使用

  1. 发布静态库
    上面我们制作好的静态库需要发布给用户。
  2. 发布头文件
    因为库文件都是一些编译生成的目标文件的集合,用户是没有源码的,所以在头文件中需要体现库中的接口,包括使用一些注释对函数功能参数以及返回值做一些说明。
  3. 使用
    用户在使用的时候只需要包含提供的头文件,就可以调用相应的接口了。我们来看一下在编译的时候如何添加该库,下面有两种常用的方式:
    方式一: gcc main.c lib/libcal.a -Iinclude -o app
    在这里插入图片描述
    方式二:gcc main.c -L lib -l cal -Iinclude -o app1
    在这里插入图片描述
  4. 查看静态库:
    使用nm命令:nm + 静态库名字,可以看到静态库包含的.o文件以及文件内的函数名字和地址。
    在这里插入图片描述

4 静态库&应用程序&可执行文件

如果使用了静态库,那么编译过程中会把静态库打包到可执行文件中。可是如果静态库很大功能很丰富,而我们的应用程序只调用了其中一个函数,难道要把整个库都打包进可执行程序吗?显然不是,下面我们来分析一下。
我们先列出库函数的源码:
在这里插入图片描述
再看一下main函数源码:

#include <stdio.h>
#include "head.h"

int main(int argc, char **argv)
{
	int a = 10;
	int b = 20;
	short c = 50;
	short d = 30;
	
	int res1 = add(a, b);
	short res2 = subShort(c, d);
	printf("sum = %d, subShort = %d\n", res1, res2);
	
	return 0;
}

我们在main()函数中只调用了静态库中的add()和subShort()函数,所以实际上打包到可执行文件中的静态库只有add.o和sub.o,也就是说我们使用了库中的某个函数,该函数对应的.o文件就会打包到可执行文件中,或者理解为打包的最小单位为.o文件。可以通过下图理解以下静态库,应用程序和可执行文件三者间的关系。
在这里插入图片描述
我们可以来验证一下,先使用nm命令查看一下可执行文件:nm 可执行文件。重点看一下“T”表示的代码段,从中我们可以看出虽然我们没有调用addShort()函数,但是该函数仍然被打包进可执行程序中,所以打包的最小单位应该是.o文件而不是函数。而且可执行文件中没有看到mul.o和div.o中的函数出现,所以也不是将整个静态库打包。
在这里插入图片描述
上面nm命令输出的每行开头的数字表示函数的地址,我们可以通过反汇编代码来验证一下。执行命令:objdump -D app > cal.dis,打开输出的cal.dis文件,我们截取关键部分,对比一下反汇编中函数的地址与上面代码中显示的函数地址完全一致。

0000000000400526 <main>:
  400526:	55                   	push   %rbp
  400527:	48 89 e5             	mov    %rsp,%rbp
  40052a:	48 83 ec 30          	sub    $0x30,%rsp
  40052e:	89 7d dc             	mov    %edi,-0x24(%rbp)
  400531:	48 89 75 d0          	mov    %rsi,-0x30(%rbp)
  400535:	c7 45 f4 0a 00 00 00 	movl   $0xa,-0xc(%rbp)
  40053c:	c7 45 f8 14 00 00 00 	movl   $0x14,-0x8(%rbp)
  400543:	66 c7 45 ee 32 00    	movw   $0x32,-0x12(%rbp)
  400549:	66 c7 45 f0 1e 00    	movw   $0x1e,-0x10(%rbp)
  40054f:	8b 55 f8             	mov    -0x8(%rbp),%edx
  400552:	8b 45 f4             	mov    -0xc(%rbp),%eax
  400555:	89 d6                	mov    %edx,%esi
  400557:	89 c7                	mov    %eax,%edi
  400559:	e8 37 00 00 00       	callq  400595 <add>
  40055e:	89 45 fc             	mov    %eax,-0x4(%rbp)
  400561:	0f bf 55 f0          	movswl -0x10(%rbp),%edx
  400565:	0f bf 45 ee          	movswl -0x12(%rbp),%eax
  400569:	89 d6                	mov    %edx,%esi
  40056b:	89 c7                	mov    %eax,%edi
  40056d:	e8 79 00 00 00       	callq  4005eb <subShort>
  400572:	66 89 45 f2          	mov    %ax,-0xe(%rbp)
  400576:	0f bf 55 f2          	movswl -0xe(%rbp),%edx
  40057a:	8b 45 fc             	mov    -0x4(%rbp),%eax
  40057d:	89 c6                	mov    %eax,%esi
  40057f:	bf a4 06 40 00       	mov    $0x4006a4,%edi
  400584:	b8 00 00 00 00       	mov    $0x0,%eax
  400589:	e8 72 fe ff ff       	callq  400400 <printf@plt>
  40058e:	b8 00 00 00 00       	mov    $0x0,%eax
  400593:	c9                   	leaveq 
  400594:	c3                   	retq   

0000000000400595 <add>:
  400595:	55                   	push   %rbp
  400596:	48 89 e5             	mov    %rsp,%rbp
  400599:	89 7d ec             	mov    %edi,-0x14(%rbp)
  40059c:	89 75 e8             	mov    %esi,-0x18(%rbp)
  40059f:	8b 55 ec             	mov    -0x14(%rbp),%edx
  4005a2:	8b 45 e8             	mov    -0x18(%rbp),%eax
  4005a5:	01 d0                	add    %edx,%eax
  4005a7:	89 45 fc             	mov    %eax,-0x4(%rbp)
  4005aa:	8b 45 fc             	mov    -0x4(%rbp),%eax
  4005ad:	5d                   	pop    %rbp
  4005ae:	c3                   	retq   

00000000004005af <addShort>:
  4005af:	55                   	push   %rbp
  4005b0:	48 89 e5             	mov    %rsp,%rbp
  4005b3:	89 fa                	mov    %edi,%edx
  4005b5:	89 f0                	mov    %esi,%eax
  4005b7:	66 89 55 ec          	mov    %dx,-0x14(%rbp)
  4005bb:	66 89 45 e8          	mov    %ax,-0x18(%rbp)
  4005bf:	0f b7 55 ec          	movzwl -0x14(%rbp),%edx
  4005c3:	0f b7 45 e8          	movzwl -0x18(%rbp),%eax
  4005c7:	01 d0                	add    %edx,%eax
  4005c9:	66 89 45 fe          	mov    %ax,-0x2(%rbp)
  4005cd:	0f b7 45 fe          	movzwl -0x2(%rbp),%eax
  4005d1:	5d                   	pop    %rbp
  4005d2:	c3                   	retq   

00000000004005d3 <sub>:
  4005d3:	55                   	push   %rbp
  4005d4:	48 89 e5             	mov    %rsp,%rbp
  4005d7:	89 7d ec             	mov    %edi,-0x14(%rbp)
  4005da:	89 75 e8             	mov    %esi,-0x18(%rbp)
  4005dd:	8b 45 ec             	mov    -0x14(%rbp),%eax
  4005e0:	2b 45 e8             	sub    -0x18(%rbp),%eax
  4005e3:	89 45 fc             	mov    %eax,-0x4(%rbp)
  4005e6:	8b 45 fc             	mov    -0x4(%rbp),%eax
  4005e9:	5d                   	pop    %rbp
  4005ea:	c3                   	retq   

00000000004005eb <subShort>:
  4005eb:	55                   	push   %rbp
  4005ec:	48 89 e5             	mov    %rsp,%rbp
  4005ef:	89 fa                	mov    %edi,%edx
  4005f1:	89 f0                	mov    %esi,%eax
  4005f3:	66 89 55 ec          	mov    %dx,-0x14(%rbp)
  4005f7:	66 89 45 e8          	mov    %ax,-0x18(%rbp)
  4005fb:	0f b7 55 ec          	movzwl -0x14(%rbp),%edx
  4005ff:	0f b7 45 e8          	movzwl -0x18(%rbp),%eax
  400603:	29 c2                	sub    %eax,%edx
  400605:	89 d0                	mov    %edx,%eax
  400607:	66 89 45 fe          	mov    %ax,-0x2(%rbp)
  40060b:	0f b7 45 fe          	movzwl -0x2(%rbp),%eax
  40060f:	5d                   	pop    %rbp
  400610:	c3                   	retq   
  400611:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  400618:	00 00 00 
  40061b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

5 静态库的优缺点

优点:

  • 发布程序时,不需要提供对应的库,因为代码被加载到程序中。
  • 库的加载速度快。

缺点:

  • 库被打包到应用程序中,导致可执行程序体积变大。
  • 库发生改变需要重新编译程序。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值