静态库和动态库浅析

静态库和动态库浅析



前言

静态库和动态库技术在目前应用广泛,他们都很重要,不同的应用场景需要不同的技术,有的地方适合用静态库,而有的地方需要使用动态库技术,所以了解两者的区别和优缺点,知道什么时候该用哪一种技术就显得很重要。


一、什么是库

库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
库有两种:静态库(.a、.lib)和动态库(.so、.dll)。在Linux下,静态库后缀为.a,动态库后缀为.so。
由于目前在学有关Linux方面的知识,所以本文所讲的库都是基于Linux的,其实windows下的库也是大同小异。以上是本人结合所学后的一点小看法,这篇博客作为我的第一篇博客,由于小白能力有限,大神勿喷哈哈!如果有错误欢迎指出!


二、静态库

静态库是一些目标文件(后缀名为.o)的集合,是一种可执行的二进制程序文件,当需要使用到某个静态库时,在链接的时候要将自己所生成的那些目标文件和引用到的静态库链接到一起生成一个可执行文件,即会将静态库复制到你的目标文件然后生成一个可执行文件。对应的链接方式称为静态链接。


三、动态库

动态库是一种不可执行的二进制程序文件,当需要使用到某个动态库时,在链接的时候不需要将动态库复制到你的目标代码中,而是在你的程序运行的时候需要用到动态库的内容时才将动态库载入到内存,而且如果此时有多个程序用到同一个动态库的内容,此时内存只需要有一份该动态库的副本即可,所有用到该动态库的程序共享这个副本。对应的链接方式称为动态链接。


四、静态库优缺点

优点:静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系,便于移植。
缺点:

  1. 直接复制到目标程序会使我们的程序变得非常的臃肿,会很浪费我们的磁盘和内存资源(运行时)。如:运行时,在内存中不同的程序如果要使用同一份静态库的时候,每个程序都需要复制一份静态库到自己的程序中,非常的占用内存。
  2. 当需要更新某个静态库的时候,使用到该静态库的程序需要整个重新进行链接生成。

五、动态库优点


  1. 动态库在程序运行时由系统动态加载到内存中供程序调用。使用动态库的优点是系统只需载入一次动态库,不同的程序可以得到内存中相同的动态库的副本,因此节省了很多内存。
  2. 当需要对动态库进行更新时,无需将整个程序进行重新生成,只需要单独对需要更新的动态库进行更新,当重新运行你的程序的时候,在动态链接的时候就会把已经更新的动态库进行链接。

六、静态库的创建和使用

1、创建

在这里插入图片描述

  • 首先,编写.c文件,然后通过预处理、编译、汇编生成一组目标文件
  • 然后通过下面的打包指令将目标文件打包成静态库文件(.a)
ar src libmymath.a add.o sub.o div1.o mul.o

这里的ar是打包工具,src 是跟随的参数 
libmymath.a是打包后的静态库名,格式为:lib库名.a 
后面是一组目标文件

一点习惯1

2、使用

gcc test.c  -o test -l./lib/mymath  -I ./inc
注意使用的时候静态库要去掉前缀lib和后缀.a(静态链接的时候就不能去掉)

test.c是你的程序
-l./lib/libmymath.a指定静态库所在的目录
-I ./inc 指定静态库头文件所在的目录

七、动态库的创建和使用

1、创建

在这里插入图片描述

  • 首先,将.c文件生成.o文件,此过程需要生成与位置无关的代码(使用-fPIC参数),命令如下:
gcc -c add.c -o add.o -fPIC
gcc -c sub.c -o sub.o -fPIC
gcc -c div.c -o div.o -fPIC
  • 使用 gcc -shared 制作动态库
gcc -o -shared lib库名.so add.o sub.o div.o

2、使用

  • 编译生成可执行程序
gcc test.c -o a.out -lmymath -L./lib -I./inc
注意使用的时候动态库要去掉前缀lib和后缀.so(动态链接的时候就不能去掉)

这里的 -l指定动态库名  -L指定动态库路径  -I指定动态库头文件
  • 最后运行 ./a.out,但是会出错!!!
    原因。2
  • 解决方案:
  1. 通过环境变量:
export  LD_LIBRARY_PATH=动态库路径
但是这样有个缺点,就是重启终端后再次执行./a.out还是会报错,这是因为,环境变量是进程的概念,你设置的变量是在当前终端进程下设置的,也就是只在当前终端有效,当你新创建一个终端的时候,相当于运行了一个新的进程,此时该进程读取的环境变量是新创建进程的默认环境变量,而不是你之前新设置的那个环境变量了。
  1. 永久生效:写入 终端配置文件 ~/.bashrc
    写入 export LD_LIBRARY_PATH=动态库路径 (建议使用绝对路径),修改后记得要让修改后的~/.bashrc 生效,生效方法:(1). .bashrc/ (2) source .bashrc/ (3)重启终端
  2. 拷贝 自定义动态库到 /lib(标准C库所在的目录位置,这样当进行动态链接的时候动态链接器会到这个目录去找寻找你的动态链接库)
  3. 配置 /etc/ld.so.conf文件
1)sudo vim  /etc/ld.so.conf
2)写入动态库绝对路径 然后保存
3)sudo ldconfig -v 使配置文件生效

注:可以使用 ldd a.out 查看此可执行程序的动态链接库所链接的目录,如果没有链接到所需的动态库路径,就会显示 没有找到文件。


  1. 我会建一个lib目录来存放打包的静态库文件,然后建立一个inc目录来存放静态库头文件,这样子到时候需要将自己的静态库分享出去的时候,只需要把 lib 和对应的 inc 这两个目录发送出去。 ↩︎

  2. 这是因为程序运行时也需要指定动态链接库的路径,才能在运行时找到库代码,以下提供4种方法来解决此问题。 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,有两种内部类:静态内部类和非静态内部类。它们的主要区别在于访问方式和用途。 静态内部类是一个独立的类,但它是作为宿主类的一个静态成员存在的。它可以访问宿主类的静态成员,但不能直接访问宿主类的非静态成员。另外,静态内部类的实例化不依赖于宿主类的实例化,可以直接通过宿主类访问或使用。静态内部类通常用于将一个类嵌套在另一个类中,并与其它外部类共享。 非静态内部类是一个依赖于宿主类实例的类,它只能在宿主类的实例中被实例化。非静态内部类可以直接访问宿主类的成员,包括静态和非静态成员。非静态内部类的实例化必须依赖于宿主类的实例,并通过宿主类的实例访问或使用。非静态内部类通常用于充当宿主类的辅助类,以提供更多特定于宿主类实例的功能。 总结起来,静态内部类可以看作是宿主类的静态成员,独立于宿主类的实例存在,并且可以直接使用宿主类的静态成员;非静态内部类是宿主类的一部分,依赖于宿主类的实例存在,并且可以直接使用宿主类的所有成员。 在实际应用中,选择使用静态内部类还是非静态内部类取决于具体需求。如果一个类不依赖于宿主类的实例,且能够独立使用,那么可以使用静态内部类;如果一个类需要依赖于宿主类的实例,并且需要访问宿主类的成员,那么就需要使用非静态内部类。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值