GCC 编译使用动态链接库和静态链接库

转载 2013年12月03日 21:08:45

http://blog.csdn.net/orzlzro/article/details/6460058

1 库的分类

根据链接时期的不同,库又有静态库和动态库之分。

静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。

有别于静态库,动态库的链接是在程序执行的时候被链接的。所以,即使程序编译完,库仍须保留在系统上,以供程序运行时调用。(TODO:链接动态库时链接阶段到底做了什么)

2 静态库和动态库的比较

链接静态库其实从某种意义上来说也是一种粘贴复制,只不过它操作的对象是目标代码而不是源码而已。因为静态库被链接后库就直接嵌入可执行文件中了,这样就带来了两个问题。

首先就是系统空间被浪费了。这是显而易见的,想象一下,如果多个程序链接了同一个库,则每一个生成的可执行文件就都会有一个库的副本,必然会浪费系统空间。

再者,人非圣贤,即使是精心调试的库,也难免会有错。一旦发现了库中有bug,挽救起来就比较麻烦了。必须一一把链接该库的程序找出来,然后重新编译。

而动态库的出现正弥补了静态库的以上弊端。因为动态库是在程序运行时被链接的,所以磁盘上只须保留一份副本,因此节约了磁盘空间。如果发现了bug或要升级也很简单,只要用新的库把原来的替换掉就行了。

那么,是不是静态库就一无是处了呢?

答曰:非也非也。不是有句话么:存在即是合理。静态库既然没有湮没在滔滔的历史长河中,就必然有它的用武之地。想象一下这样的情况:如果你用libpcap库编了一个程序,要给被人运行,而他的系统上没有装pcap库,该怎么解决呢?最简单的办法就是编译该程序时把所有要链接的库都链接它们的静态库,这样,就可以在别人的系统上直接运行该程序了。

所谓有得必有失,正因为动态库在程序运行时被链接,故程序的运行速度和链接静态库的版本相比必然会打折扣。然而瑕不掩瑜,动态库的不足相对于它带来的好处在现今硬件下简直是微不足道的,所以链接程序在链接时一般是优先链接动态库的,除非用-static参数指定链接静态库。

 

 

 

动态链接库

1. 创建动态链接库

  1. #include<stdio.h>  
  2. void hello()  
  3. {  
  4.         printf("hello world/n");  
  5. }  
 

用命令gcc -shared hello.c -o libhello.so编译为动态库。可以看到,当前目录下多了一个文件libhello.so。

 

2. 再编辑一个测试文件test.c,内容如下

  1. #include<stdio.h>  
  2. int main()  
  3. {  
  4.         printf("call hello()");  
  5.         hello();  
  6. }  
 

编译 gcc test.c -lhello

-l 选项告诉编译器要使用hello这个库。奇怪的地方是动态库的名字是libhello.so,这里却使用hello.

 

但这样还不行,编译会出错。

In function `main':

 

test.c:(.text+0x1d): undefined reference to `hello'

collect2: ld returned 1 exit status

 

这是因为hello这个库在我们自己的路径中,编译器找不到。

需要使用-L选项,告诉hello库的位置

 

gcc test.c -lhello -L. -o test

 

-L .告诉编译器在当前目录中查找库文件

 

 

3. 编译成功后执行./test, 仍然出错

说找不到库

 

有两种方法:

一、可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig(要有root权限才行)。

二、把当前路径加入环境变量LD_LIBRARY_PATH中

 

当然,如果你觉得不会引起混乱的话,可以直接把该库拷入/lib,/usr/lib/等位置(无可避免,这样做也要有权限),这样链接器和加载器就都可以准确的找到该库了。

 

 

我们采用第二种方法:

 

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

 

这样,再执行就成功了。

 

 

 

 

 

下面再讲讲静态链接库

仍使用刚才的hello.c和test.c。

 

1. gcc -c hello.c 注意这里没有使用-shared选项

2. 把目标文件归档    ar -r libhello.a hello.o

 

 

    程序 ar 配合参数 -r 创建一个新库 libhello.a 并将命令行中列出的对象文件插入。采用这种方法,如果库不存在的话,参数 -r 将创建一个新的库,而如果库存在的话,将用新的模块替换原来的模块。

3. 在程序中链接静态库

           gcc test.c -lhello -L. -static -o hello.static 

 

 

或者   gcc test.c libhello.a -L. -o hello.static

 

生成的hello.static就不再依赖libhello.a了

 

 

 

 

 

 

两个有用的命令

 

 

file程序是用来判断文件类型的,在file命令下,所有文件都会原形毕露的。

顺便说一个技巧。有时在 windows下用浏览器下载tar.gz或tar.bz2文件,后缀名会变成奇怪的tar.tar,到Linux有些新手就不知怎么解压了。但 Linux下的文件类型并不受文件后缀名的影响,所以我们可以先用命令file xxx.tar.tar看一下文件类型,然后用tar加适当的参数解压。

 

 

另外,还可以借助程序ldd实用程序来判断。

ldd是用来打印目标程序(由命令行参数指定)所链接的所有动态库的信息的,如果目标程序没有链接动态库,则打印“not a dynamic executable”,ldd的用法请参考manpage。

GCC 编译使用动态链接库和静态链接库的方法

1 库的分类 根据链接时期的不同,库又有静态库和动态库之分。 静态库是在链接阶段被链接的,所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。 有别于静态库,动态库的链接是在程...
  • yuan1164345228
  • yuan1164345228
  • 2015年06月04日 09:29
  • 3271

GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结

GCC 编译使用动态链接库和静态链接库 1 库的分类 根据链接时期的不同,库又有静态库和动态库之分。 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影...
  • benpaobagzb
  • benpaobagzb
  • 2016年05月10日 16:07
  • 7021

编译动态链接库.so和静态链接库.a

名词介绍 静态函数库 这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数...
  • lylwo317
  • lylwo317
  • 2016年05月02日 12:35
  • 1934

gcc编译链接库并调用链接库的方法

linux系统下gcc编译静态链接库和动态链接库的方法
  • u010851789
  • u010851789
  • 2016年01月06日 14:21
  • 1004

gcc/g++ 链接库的编译与链接

程序编译一般需要经预处理、编译、汇编和链接几个步骤。在实际应用中,有些公共代码需要反复使用,就把这些代码编译成为“库”文件。在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中,这种...
  • u010229420
  • u010229420
  • 2016年05月04日 11:59
  • 4781

linux gcc 静态编译和动态编译

一.编译和链接选项: 第一步:预编译。 gcc -E hello.c -o hello.i -E参数: GCC在完成预处理后,停止编译过程。 预处理的宏定义展开到 hello.i中。...
  • gwzz1228
  • gwzz1228
  • 2013年11月21日 16:28
  • 7510

gcc调试中使用静态连接库和动态链接库以及-I -l L含义

静态链接库与动态链接库都是共享代码的方式, 区别: 如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。静态库的代码在编译过程中已经被载入可执行程序,...
  • qq_21034239
  • qq_21034239
  • 2017年01月12日 22:08
  • 1344

静态链接库和动态链接库的区别及优缺点

文章出处:http://www.cnblogs.com/gaoyihan/p/4723332.html     静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不...
  • MACMACip
  • MACMACip
  • 2017年01月21日 14:50
  • 2649

gcc链接g++编译生成的静态库和动态库的makefile示例

使用c++开发程序或者库时,将库提供给其他人使用。 然而使用者是使用c开发的程序,链接g++编译生成的库时,于链接gcc生成的库,有所不同。 首先是静态库,以链接g++编译生成的libmylib....
  • caoyaobin
  • caoyaobin
  • 2017年01月31日 12:17
  • 483

用gcc编译生成动态链接库*.so文件的方法。

linux下文件的类型是不依赖于其后缀名的,但一般来讲: .o,是目标文件,相当于windows中的.obj文件 .so 为共享库,是shared object,用于动态连接的,和dll差不多 ...
  • ngvjai
  • ngvjai
  • 2013年01月19日 21:14
  • 10096
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:GCC 编译使用动态链接库和静态链接库
举报原因:
原因补充:

(最多只允许输入30个字)