静态库和动态库 笔记


爱编程的大丙
学习笔记

三、静态库和动态库

程序中调用的库有两种 静态库和动态库,不管是哪种库文件本质是还是二进制的源文件。

在项目中使用库一般有两个目的,一个是为了使程序更加简洁不需要在项目中维护太多的源文件,另一方面是为了源代码保密,毕竟不是所有人都想把自己编写的程序开源出来。

3.1 静态库

在 Linux 中静态库由程序 ar 生成,现在静态库已经不像之前那么普遍了,这主要是由于程序都在使用动态库。关于静态库的命名规则如下:

  • 在 Linux 中静态库以 lib 作为前缀,以.a 作为后缀,中间是库的名字自己指定即可,即: libxxx.a
  • 在 Windows 中静态库一般以 lib 作为前缀,以 lib 作为后缀,中间是库的名字需要自己指定,即: libxxx.lib
3.1.1 生成静态链接库

生成静态库,需要先对源文件进行汇编操作 (使用参数 -c) 得到二进制格式的目标文件 (.o 格式), 然后在通过 ar 工具将目标文件打包就可以得到静态库文件了 (libxxx.a)。

使用 ar 工具创建静态库的时候需要三个参数:

  • 参数c:创建一个库,不管库是否存在,都将创建。
  • 参数s:创建目标文件索引,这在创建较大的库时能加快时间。
  • 参数r:在库中插入模块 (替换)。默认新的成员添加在库的结尾处,如果模块名已经在库中存在,则替换同名的模块。

image-20211003095852678

生成静态链接库的具体步骤:

  1. 需要将源文件进行汇编,得到 .o 文件,需要使用参数 -c
# 执行如下操作, 默认生成二进制的 .o 文件
# -c 参数位置没有要求
$ gcc 源文件(*.c) -c	
  1. 将得到的 .o 进行打包,得到静态库
$ ar rcs 静态库的名字(libxxx.a) 原材料(*.o)
  1. 发布静态库
1. 提供头文件 **.h
2. 提供制作出来的静态库 libxxx.a
3.1.2 静态库的使用

当我们得到了一个可用的静态库之后,需要将其放到一个目录中,然后根据得到的头文件编写测试代码,对静态库中的函数进行调用。

注意:

编译的源文件中包含了头文件 head.h, 这个头文件中声明的函数对应的定义(也就是函数体实现)在静态库中,程序在编译的时候没有找到函数实现,因此提示 undefined reference to xxxx

解决方案:在编译的时将静态库的路径和名字都指定出来

-L: 指定库所在的目录 (相对或者绝对路径)
-l: 指定库的名字,需要掐头 (lib) 去尾 (.a) 剩下的才是需要的静态库的名字

3.2 动态库

动态链接库是程序运行时加载的库,当动态链接库正确部署之后,运行的多个程序可以使用同一个加载到内存中的动态库,因此在 Linux 中动态链接库也可称之为共享库。

动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的。库中函数和变量的地址使用的是相对地址(静态库中使用的是绝对地址),其真实地址是在应用程序加载动态库时形成的。

动态库命名规则:

  • 在 Linux 中动态库以 lib作为前缀,以.so 作为后缀,中间是库的名字自己指定即可,即: libxxx.so
  • 在 Windows 中动态库一般以 lib作为前缀,以 dll作为后缀,中间是库的名字需要自己指定,即: libxxx.dll
3.2.1 生成动态链接库

生成动态链接库是直接使用gcc 命令并且需添加-fPIC(-fpic) 以及 -shared 参数。

  • -fPIC 或 -fpic 参数的作用是使得 gcc 生成的代码是与位置无关的,也就是使用相对位置。
  • -shared参数的作用是告诉编译器生成一个动态链接库。

image-20211003123144924

生成动态链接库的具体步骤:

  1. 将源文件进行汇编操作,需要使用参数 -c, 还需要添加额外参数 -fpic /-fPIC
# 得到若干个 .o文件
$ gcc 源文件(*.c) -c -fpic
  1. 将得到的.o 文件打包成动态库,还是使用 gcc, 使用参数 -shared 指定生成动态库 (位置没有要求)
$ gcc -shared 与位置无关的目标文件(*.o) -o 动态库(libxxx.so)
  1. 发布动态库和头文件
1. 提供头文件: xxx.h
2. 提供动态库: libxxx.so
3.2.2 动态库的使用

和静态库的使用方法一样。

注意:

执行生成的可执行程序, 错误提示 ==> 可执行程序执行的时候找不到动态库。

error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory

3.2.3 解决动态库无法加载的问题

方案1

image-20211003134744286

方案2

image-20211003134802688
注意,路径是:/home/xxx/...

方案3

image-20211003134818201

3.3 优缺点

3.3.1 静态库
  • 优点:
    • 静态库被打包到应用程序中加载速度快
    • 发布程序无需提供静态库,移植方便
  • 缺点:
    • 相同的库文件数据可能在内存中被加载多份,消耗系统资源,浪费内存
    • 库文件更新需要重新编译项目文件,生成新的可执行程序,浪费时间

image-20211003135144441

3.3.2 动态库
  • 优点:
    • 可实现不同进程间的资源共享
    • 动态库升级简单,只需要替换库文件,无需重新编译应用程序
    • 程序员可以控制何时加载动态库,不调用库函数动态库不会被加载
  • 缺点:
    • 加载速度比静态库慢,以现在的计算机性能可以忽略
    • 发布程序需要提供依赖的动态库

image-20211003140052205

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ClimberCoding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值