动态库与静态库

本文深入解析静态链接库与动态链接库的原理、生成过程、使用场景和相关命令,包括静态库与动态库的区别、生成静态库与动态库的方法、链接过程、相关命令nm、ar和ldd的使用,以及如何处理不同位数的程序与库的兼容性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一,区别

静态链接是指在链接阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。

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

动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。

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

静态链接的大致过程如下图所示:



二,生成

静态链接库
1、编译生成目标文件
gcc -c struct.c
2、创建静态库(仅仅将编译后的文件进行打包)
ar rcs libstruct.a struct.o (顺序不能乱)
3、链接静态链接库,生成可执行文件
gcc main.c -static-L. -lstruct -o main

    (main.c必须放在-lstruct之前)


动态链接库:
1、编译成动态链接库
gcc struct.c -fPIC -shared-o libstruct.so

或者

gcc -c struct.c -o struct.o && gcc -shared -fPCI -o libstruct.so struct.o

(-fpic可以生成小而高效的代码,但是不同的处理器中-fpic生成的GOT(Global  Offset Table,  全局偏移表)的大小有限制,另一方面,使用-fPIC的话,任何处理器都可以放心使用。在这里,使用-fPIC。(在X86中使用-fpic和-fPIC 没有任何区别))

2、链接动态链接库,生成可执行文件
gcc main.c -L. -lstruct -o main
3、设置库文件的环境路径
1)在bashrc或profile文件里用LD_LIBRARY_PATH定义,然后用source加载。
2)把库路径添加到ld.so.conf文件中,然后用ldconfig加载。
3)ldconfig /home/user/lib,仅能暂时性使用,若下次ldconfig时此目录下的动态链接库就不能被共享
了。


三,相关命令

nm
功能:
       列出编入目标文件或二进制文件的所有符号。用途一:查看程序调用什么函数;用途二:查看一个给定的库或目标文件是否提供了所需的函数。
语法:nm [options] file
常用选项:
-C 将符号名转换为用户级的名字。在让C++函数名可读方面特别有用。
-s 当用于.a文件时,输出把符号名映射到定义该符号的模块或成员名的索引。
-u 只显示未定义的符号,即在被检查的文件外部定义的文件。
-l  使用调试信息输出定义每个符号的行号,或未定义符号的重要位项。


ar
功能:将多个.o文件组合到一起成为.a文件。
语法:ar [options] lib*.a *.o
常用选项:
-c 如果存档文件不存在,则创建,并不显示ar发出的警告。
-q 把*.o添加到存档文件末尾而不检查是否进行替换。
-r  向存档文件中插入.o文件,替换已有的任何同名文件,新成员添加到文档末尾。
-s 创建或升级从符号到.a文件之间的交叉索引映射表,并加入到.a文件中。
   等价与ranlib [*.a]。执行该命令后,可用nm –s来查看生成的索引。

-t:显示库的模块表清单。一般只显示模块名。 


ldd
功能:显示可执行程序运行所需的共享库。
语法
ldd [options] file
常用选项:
-d 执行重定位并报告所有丢失的函数。
-r 执行对函数和数据对象的重定位并报告丢失的任何函数或数据对象。


四,其它

1. 当Linux静态库和Linux动态库同名时, gcc命令将优先使用动态库

2. 如果编译的程序是32位的,所需要的动态链接库也需重新编译,例如mplayer需要用到 mp3lame,jpeg-6b,libpng等,均需要重新编译.

3. 如何知道应用程序是64位还是32位的?可使用file命令查看.

staff-1:~# file /bin/ls

4. 在64位的机器上编译32位还是64位程序,主要是要编译器和链接器上加上参数据:-m32 (编译32位) -m64(编译64)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值