Loading [MathJax]/jax/output/CommonHTML/jax.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >动态库与静态库优缺点比较分析_c静态库和动态库的区别

动态库与静态库优缺点比较分析_c静态库和动态库的区别

作者头像
全栈程序员站长
发布于 2022-11-11 07:09:59
发布于 2022-11-11 07:09:59
3.3K0
举报

大家好,又见面了,我是你们的朋友全栈君。

动态库与静态库优缺点比较

(2012-10-18 15:31)

我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期的代码维护。我们可以把他们制作成相应的功能函数,使用时直接调用就会很方便,还可以进行后期的功能升级。

例如我要在一段代码中多次交换两个变量的值,我可以在代码中多次写入

i=x; x=y; y=i;

不过这样未免有点麻烦我们可以编写一个change_two_int()函数进行简化。 定义如下函数: void change_two_int(int *a,int *b) { int c; c=*a; *a=*b; *b=c; } 这样每次要进行交换时只需调用 change_two_int(&x , &y);即可,是否方便了许多?

那么我们要讨论的和这些有什么关系呢?库通俗的说就是把这些常用函数的目标文件打包在一起,提供相应函数的接口,便于程序员使用。库是别人写好的现有的,成熟的,可以复用的代码,我们只需要知道其接口如何定义,便可以自如使用。

现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。比如我们常使用的printf函数,就是c标准库提供的函数。我们在使用时只需要包含相应的头文件就可以使用(非静态编译还要有相应的库文件)。而不用关心printf函数具体是如何实现的,这样就大大提高了程序员编写代码的效率。从使用方法上分库大体上可以分为两类:静态库和共享库。在windows中静态库是以 .lib 为后缀的文件,共享库是以 .dll 为后缀的文件。在linux中静态库是以 .a 为后缀的文件,共享库是以 .so为后缀的文件。 以linux下的静态库和动态库为例我们研究一下,首先我们看一下他们的生成方式

静态库: 首先将源文件编译成目标文件:gcc –c a.c b.c 生成静态库:ar –rc libstatic.a a.o b.o

共享库: 同静态库一样编译成目标文件:gcc –c a.c b.c 生成共享库:gcc –fPIC –shared –o libshared.so a.o b.o

由此可见静态库和动态库都是对目标文件的处理,也可以说库文件已经是机器码文件了,静态库和共享库的加载过程有很大的区别。

静态库的链接方法: gcc –o staticcode –L. –lstatic main.c –static(默认库在当前文件夹)

共享库的链接方法: gcc –o sharedcode -L. –lshared main.c(默认库在当前文件夹)

当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被copy到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,这样运行起来相对就快些。不过会有个缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间.

与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中。这样就使可执行文件比较小, 节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率,没有好与坏的区别,只看具体需要了。

另外,.一个程序编好后,有时需要做一些修改和优化,如果我们要修改的刚好是库函数的话,在接口不变的前提下,使用共享库的程序只需要将共享库重新编译就可以了,而使用静态库的程序则需要将静态库重新编译好后,将程序再重新编译一便。

总结:

一、库的类型

(一) 在windows中

.dll 动态库

.lib 静态库

库即为源代码的二进制文件

(二) 在linux中

.so 动态库

.a 静态库

(三) 静态库和动态库的优缺点

我们通常把一些公用函数制作成函数库,供其它程序使用。

函数库分为静态库和动态库两种。

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在

1.什么是库

在windows平台和linux平台下都大量存在着库。

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。

由于windows和linux的本质不同,因此二者库的二进制是不兼容的。

本文仅限于介绍linux下的库

2.库的种类

linux下的库有两种:静态库和共享库(动态库)。

二者的不同点在于代码被载入的时刻不同。

静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。

共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

3.库存在的意义

库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。

现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。

4.库文件是如何产生的在linux下

静态库的后缀是.a,它的产生分两步

Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表

Step 2.ar命令将很多.o转换成.a,成文静态库

动态库的后缀是.so,它由gcc加特定参数编译产生。

例如:

gcc -shared -Wl,-soname, libfoo.so.1 -olibfoo.so.1.0 *.

5.库文件是如何命名的,有没有什么规范

在linux下,库文件一般放在/usr/lib和/lib下,

静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称

动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号

6.如何知道一个可执行程序依赖哪些库

ldd命令可以查看一个可执行程序依赖的共享库,

例如# ldd /bin/lnlibc.so.6

=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2

=> /lib/ld- linux.so.2 (0×40000000)

可以看到ln命令依赖于libc库和ld-linux库

7.可执行程序在执行的时候如何定位共享库文件

当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径

此时就需要系统动态载入器(dynamiclinker/loader)

对于elf格式的可执行程序,是由ld-linux.so*来完成的

它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目录

找到库文件后将其载入内存

8.在新安装一个库之后如何让系统能够找到他

如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下

1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

2.运行ldconfig,该命令会重建/etc/ld.so.cache文件

############################################################

linux中编译静态库(.a)和动态库(.so)的基本方法

(四) 静态库

在linux环境中, 使用ar命令创建静态库文件.如下是命令的选项:

d —–从指定的静态库文件中删除文件

m —–把文件移动到指定的静态库文件中

p —–把静态库文件中指定的文件输出到标准输出

q —–快速地把文件追加到静态库文件中

r —–把文件插入到静态库文件中

t —–显示静态库文件中文件的列表

x —–从静态库文件中提取文件

还有多个修饰符修改以上基本选项,详细请man ar 以下列出三个:

a —–把新的目标文件(*.o)添加到静态库文件中现有文件之后

b—–***************************************之前

v —–使用详细模式

ar 命令的命令行格式如下:

ar[-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files…

参数archive定义库的名称, files是库文件中包含的目标文件的清单, 用空格分隔每个文件.

比如创建一个静态库文件的命令如下:

ar r libapue.a error.oerrorlog.o lockreg.o

这样就了libapue.a静态库文件, 可以用 t 选项显示包含在库中的文件

创建库文件之后,可以创建这个静态库文件的索引来帮助提高和库连接的其他程序的编译速度:

使用ranlib程序创建库的索引,索引存放在库文件内部.

ranlib libapue.a

用nm程序显示存档文件的索引,它可以显示目标文件的符号

nm libapue.a | more

如果是显示目标文件的符号:

nm error.o | more

如何使用呢?如下所示:

gcc -o test test.c libapue.a

这样就可以在test.c中调用在libapue.a中的函数了.

(五) 动态库

1.创建共享库

gcc -shared -o libapue.soerror.o errorlog.o

这样就创建了共享库!

2.编译共享库

假设共享库位于当前目录(即跟程序文件相同的目录中)

gcc -o test -L. -lapue test.c

这样就编译出了不包含函数代码可执行文件了,但是但你运行时会发现linux动态加载器找不到libapue.so文件.

可以用ldd 命令查看可执行文件依赖什么共享库:

ldd test

如何才能让动态加载器发现库文件呢?有两种方法可以解决:

1.环境变量

exportLD_LIBRARY_PATH=”$LD_LIBRARY_PATH:.”

2.修改/etc/ld.so.conf文件.

一般应用程序的库文件不与系统库文件放在同一个目录下,一般把应用程序的共享库文件放在/usr/local/lib下,新建一个属于自己的目录apue,然后把刚才libapue.so复制过去就行了

同时在/etc/ld.so.conf中新增一行:

/usr/local/lib/apue

以后在编译程序时加上编译选项:

-L /usr/local/lib/apue -lapue

/*

参数的配置通过mangcc可以看到

-llibrary

连接名为 library 的 库文件.

连接器 在 标准搜索目录 中 寻找 这个 库文件, 库文件 的 真正 名 字

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/187663.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月29日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux下的静态库与动态库
在windows平台和linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于windows和linux的本质不同,因此二者库的二进制是不兼容的。本文仅限于介绍linux下的库。
xxpcb
2024/07/22
2030
Linux下的静态库与动态库
linux动态库和静态库
http://blog.163.com/xychenbaihu@yeah/blog/static/13222965520101023104745738/
bear_fish
2018/09/20
12.6K0
c++动态库和静态库的区别_静态库里面包含动态库
C++静态库与动态库
全栈程序员站长
2022/11/11
2K0
Linux下动态库(.so)和静态库(.a) 的区别
动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。
bear_fish
2018/09/20
17.5K0
linux动态库和静态库的使用_静态库的使用
例如,用test1.c、test2.c、test3.c、test4.c以及main1.c形成可执行文件,我们需要先得到各个文件的目标文件test1.o、test2.o、test3.o、test4.o以及main1.o,然后再将这写目标文件链接起来,最终形成一个可执行程序。
全栈程序员站长
2022/11/11
4.9K0
Linux静态库与动态库加载
        关于库相比大家之前肯定使用过,比如C/C++里面的标准库,STL里面的各种库,我们在调用STL里的容器时都需要使用库,那么库到底是什么呢?
咬咬
2024/06/12
3440
Linux静态库与动态库加载
Linux基础——gcc编译、静态库与动态库(共享库)
1、静态库的命名格式 lib + 库的名字 + .a 例:libMyTest.a (MyTest为静态库的名字)
全栈程序员站长
2022/11/10
8.9K0
Linux基础——gcc编译、静态库与动态库(共享库)
深入浅出链接库 | 静态库与动态库
不管是在 Windows 下开发,还是在 Linux 下开发,我们都会经常性的使用一些库文件,这些库文件的特点就是,我们可以看到接口的原型并通过这些接口来调用这个函数的功能,但是我们无法查看这个功能的实现。这就是库文件,功能提供者把头文件和库文件发布给我们,我们便可以根据头文件中的接口去调用库文件中实现的功能,并且对我们隐藏了功能实现的源码和细节。其实,链接库(动态库和静态库)并没有什么神秘的,本文就带你一起解开链接库的神秘面纱,让大家自己也可以动手制作动态库与静态库。
mindtechnist
2024/08/08
7770
深入浅出链接库 | 静态库与动态库
动态库与静态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
二肥是只大懒蓝猫
2023/03/30
2.4K0
动态库与静态库
【Linux】动静态库(超详细)
💢 由于CentOS 8系统2021年12月31日已停止维护服务,CentOS 7系统将于2024年06月30日停止维护服务。CentOS官方不再提供CentOS 9及后续版本,不再支持新的软件和补丁更新。CentOS用户现有业务随时面临宕机和安全风险,并无法确保及时恢复。
IsLand1314
2024/11/19
1020
【Linux】动静态库(超详细)
【Linux】掌握库的艺术:我的动静态库封装之旅
在计算机编程中,库(Library)是一个预先编写的代码集合,包含了可以被其他程序调用的函数、类、变量和资源。库的主要目的是为了简化编程过程,提供常用功能的实现,促进代码重用,从而减少开发时间和提高软件的可靠性。
Yui_
2024/11/19
1020
【Linux】掌握库的艺术:我的动静态库封装之旅
【Linux】静态库和动态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
YoungMLet
2024/03/01
9410
【Linux】静态库和动态库
Linux:基础IO(三.软硬链接、动态库和静态库、动精态库的制作和加载)
上次介绍了基础IO(二):Linux:基础IO(二.缓冲区、模拟一下缓冲区、详细讲解文件系统)
是Nero哦
2024/07/01
2910
Linux:基础IO(三.软硬链接、动态库和静态库、动精态库的制作和加载)
【Linux】————动静态库
现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
用户11036582
2024/10/23
1460
【Linux】————动静态库
深入浅出动静态库
  当你在Linux系统上编写和运行程序时,动态库和静态库是两个非常重要的概念。它们不仅影响着程序的编译和执行效率,还直接关系到程序的可移植性和灵活性
用户11029129
2024/06/04
1510
深入浅出动静态库
【Linux】静态库和动态库
系统层面上有.和…硬链接指向目录。假设我们是超级用户,允许给目录建立硬链接,给根目录建立硬链接,从根目录开始查找,当查找硬链接的时候就是根目录,这时候递归式查找,形成了环路查找,最后导致软件无法正常进行查找工作!所以不允许普通用户给目录建立硬链接。
平凡的人1
2023/10/15
4850
【Linux】静态库和动态库
Linux gcc编译生成静态库和共享动态库的过程
这篇文章主要通过实例演示在Linux下如何使用gcc分别编译生成静态库和动态库文件以及其它程序如何使用这个生成的静态库和动态库。
typecodes
2024/03/29
8040
Linux gcc编译生成静态库和共享动态库的过程
【Linux】软硬连接与动静态库
硬连接不是一个独立的文件,因为它没有的独立的inode号,用的是目标文件的inode
用户11029103
2025/03/10
1000
【Linux】软硬连接与动静态库
Linux之动态库和静态库
我们了解了动态库和静态库的相关概念,但是我们还是不理解库是个什么东西。 假设,我们做了一个小程序,只希望提供给用户小程序的功能,不希望暴露我们的源码。我们可以选择给用户提供我们的.o可重定位目标二进制文件(gcc -c 文件)与头文件。让用户使用我们提供的.o文件和.h文件进行链接即可。(在编译时,只需要把源文件编译成.o文件,再将其链接即可形成一个可执行程序,因此我们可以直接提供,o文件)。 文件add.c
摘星
2023/10/15
7260
Linux之动态库和静态库
静态链接库和动态链接库的区别
Linux下得库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。面对比一下两者:
狼啸风云
2019/11/03
8.6K0
相关推荐
Linux下的静态库与动态库
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档