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

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

(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 -fPIC -c *.c $ 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 的 库文件.

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

转载自:http://blog.csdn.net/sunshinewave/article/details/39155755

时间: 2024-10-13 05:45:45

动态库与静态库优缺点比较的相关文章

对动态库和静态库的一些总结

动态库和静态库 区 别 静态库 动态库 将库文件中的二进制代码直接链接到目标文件,程序运行时不再需要库: 将接口在库文件中的位置信息链接到目标文件,程序运行时再根据这些位置信息进行调用,因此运行时需要库文件: lib 中的指令都全部被直接包含在最终生成的目标文件中了: dll不必被包含在最终目标文件中,目标文件执行时可以“动态”地引用和卸载dll文件: 静态链接库中不能再包含其他的动态链接库或者静态库: 动态链接库中还可以再包含其他的动态或静态链接库: 优缺点 静态库 动态库 静态库只需要编译的

Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf 动态库的后缀为*.so 静态库的后缀为 libxxx.a ldconfig 目录名

Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf  动态库的后缀为*.so  静态库的后缀为 libxxx.a   ldconfig   目录名 转载自:http://blog.chinaunix.net/uid-23069658-id-3142046.html 今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在这之前,我们需要了解一下源代码到可执行程序之间到底发生了什么神奇而美妙的事情. 在Linux操作系统中,普遍使用ELF格

如何使用Eclipse的NDK开发动态库,静态库

============问题描述============ 如何使用Eclipse的NDK开发动态库,静态库? Eclipse中已经安装了NDK,CDT和Esequoyah并配置(是在网上查的). 我是做C++的,公司业务需要自学Android,对Java也是知道一点皮毛. 在网上查了一些资料,我都没有成功做出最简单的动态库或静态库,郁闷啊! 有没有详细指导? ============解决方案1============ 你去搜一下Android的jni开发,就知道了,一点都不难,不过一般开发ndk

动态库和静态库

 1.静态库不需要main函数,要想生成lib,要修改属性à常规à配置类型à改成dll 2.静态库中的头文件只是说明,是给程序员看的,其实lib里面已经有了接口. 3.链接lib的时候程序的体积就变大了. 4.静态库更新的时候,需要重新生成,然后调用 5.动态库调用就不用重新生成. 6.动态库的调用代码:(使用的是HMODULELoadLibraryA的方式进行调用) 接口 7.编写的动态库如下: #include<stdio.h> #include<stdlib.h> #in

Linux系统中“动态库”和“静态库”那点事儿【转】

转自:http://blog.chinaunix.net/uid-23069658-id-3142046.html 今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在这之前,我们需要了解一下源代码到可执行程序之间到底发生了什么神奇而美妙的事情. 在Linux操作系统中,普遍使用ELF格式作为可执行程序或者程序生成过程中的中间格式.ELF(Executable and Linking Format,可执行连接格式)是UNIX系统实验室(USL)作为应用程序二进制

ios 开发中 动态库 与静态库的区别

使用静态库的好处 1,模块化,分工合作 2,避免少量改动经常导致大量的重复编译连接 3,也可以重用,注意不是共享使用 动态库使用有如下好处: 1使用动态库,可以将最终可执行文件体积缩小 2使用动态库,多个应用程序共享内存中得同一份库文件,节省资源 3使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的. 从1可以得出,将整个应用程序分模块,团队合作,进行分工,影响比较小. 等其他好处, 从2可以看出,其实动态库应该叫共享库,那么从这个意义上来说,苹果禁止iOS开

函数库:静态库和动态库

1.函数库 函数库其实就是一些写好的函数集合,方便别人的复用.实现的封装之后,最终的目的都是给别人调用. 2.库的形式 库的形式分:动态链接库和静态链接库. 优点: (1)库文件都是被编译好的二进制文件,别人看不到源代码,可以保持保密:(2)同时不会因为不小心被修改出现问题,便于维护. LINUX 下的库学习: 静态链接库:.a 文件 其实就是将多函数,做编译但是不链接生成的 .o 文件,使用 ar 工具打包为 .a 的文件.编译的阶段,当调用这些库的时候,链接器就会去 .a 的库文件中拿出被调

VS2008 动态库和静态库的生成和加载

第一:动态库和静态库的生成: 1) 新建一个生成dll工程: 文件->新建->项目->Win32->Win32控制台应用程序 输入项目名称:dllTest ,项目路径:D:\VC 确定 下一步 应用程序类型:选择DLL 完成 2) 编写代码: 2-1) 增加一个头文件:dllTest.h #define ICILIB_UTIL_API __declspec(dllexport)  //生成动态库时,同时在Debug或Release目录下生成.lib和.dll文件. class IC

linux动态库与静态库使用比较

在windows下,动态库dll的使用往往伴随着lib的指引,而linux使用动态库和静态库则有较大的不同. linux静态库和动态库的区别 1. 静态库 名字一般是libxxx.a:利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,编译后的执行程序不需要外部的函数库支持,但是,升级比较麻烦.每一次版本更新都需要重新编译. 2. 动态库 名字一般是libxxx.so;动态库没有被编译进最终程序,只有在需要的时候,动态加载到内存中.编译后的程序不包含动态库部分,程