静态编译与动态编译

概念和比较


   库可以有三种使用的形式:静态、共享和动态。静态库的代码在编译时就已连接到开发人员开发的应用程序中,而共享库只是在程序开始运行时才载入,在编译时,只是简单地指定需要使用的库函数。动态库则是共享库的另一种变化形式。动态库也是在程序运行时载入,但与共享库不同的是,使用的库函数不是在程序运行开 始,而是在程序中的语句需要使用该函数时才载入。动态库可以在程序运行期间释放动态库所占用的内存,腾出空间供其它程序使用。由于共享库和动态库并没有在程序中包括库函数的内容,只是包含了对库函数的引用,因此代码的规模比较小。


静态编译,会在连接的时候就将需要使用的库(一般是从.a文件)编译进可执行文件之中,故而在程序执行的时候就不需要调用.a文件了。这种方式优点是文件的执行不需要依赖其他的库,因此增加了文件的独立性。缺点就是当功能复杂,代码量大的时候,可执行文件会过于庞大。造成文件的加载和初始化比较困难,尤其是硬件很一般的情况下。


  同时,静态编译虽然保证了程序一定的独立不依赖性,但是如果库文件升级,要想使用更优的库文件,则必须重新编译。


   动态编译则不同,一般先把库函数编译成.so动态库。在链接的时候,可执行文件中并不会包含要使用的库函数,只是说明要使用哪些动态库.so文件。这种方式的优点是,链接后的可执行文件比较小,便于加载使用,而且也对内存要求没有静态编译那么高。相对应,由于要使用一些.so文件,因此可执行文件必须依赖于其他动态库文件.so文件,在程序移动等时候都需要考虑其依赖关系。一个好处是,动态库更新后,可执行文件不用重新编译就可使用新动态库的优化特性,只要接口和.so文件名匹配。


生成静态库:


  1. $ gcc -c func.c -o func.o 产生目标文件

  2. $ ar rcs libfunc.a func.o  用目标文件产生静态库

  3. $ gcc main.c -o main -static -L. -lfunc 链接产生可执行文件

  4. $ ./main 


生成动态库:


1$ gcc -fPIC -cfunc.c -o func.o 同样产生目标文件,不管动态还是静态连接,首先要产生目标文件.o文件


2$ gcc -shared -olibfunc.so.1.0.0 func.o  gcc –share产生共享库文件


3$ ln -slibfunc.so.1.0.0 libfunc.so   对版本的一个控制,便于连接


4$ gcc main.c -o main-L. –lfunc     链接产生可执行文件


5$ exportLD_LIBRARY_PATH=$(pwd) 配置动态库文件,这个也可以通过编辑/etc/ld.so.conf,在其中加入库文件的目录来实现。同时使用ldconfig来更新动态库。


遇到下面问题一般是动态库没有配置正确:


libmyhello.so:cannot open shared object file: No such


6$ ./main


如果将 so文件 copy到系统 lib目录(/usr/lib),则最后 2步就不用了。


需要注意:

不管是动态编译还是静态编译,都只是说明了库文件的使用方式。但是,链接时候使用的命令都是一样。只是编译工具会自动根据库文件的类型选择链接方式,要不要把库函数包含进可执行文件中。特别注意的是,如果目录下存在同名的静态库和动态库文件,则默认会使用动态编译方式。比如同时存在libmyhello.alibmyhello.so.


最后还有 3个小知识:


1.   nm 命令:列出目标文件或 2进制文件的所有符号。

2.ldd命令:列出为了使程序正常运行所需要的所有共享库。ldd lmp_linux.


3. /etc/ld.so.conf 文件:除了标准目录(/lib/usr/lib)之外,链接器 和加载器搜索共享库时要检查的其他目录,和这个文件相关的一个命令是:ldconfig






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值