静态库是在链接阶段被链接的,所以生成的可执行文件就不受库的影响,即使库被删除,程序依然可以成功运行。
而依赖动态库的程序其实也有链接动态库的阶段,只不过这个链接并不是真正的将动态库链接到程序中,其目的是告诉程序,所依赖的到底是哪个动态库。
静态库有点类似于将静态库复制到程序中,而动态库是在程序中创建一个软连接。
比如:
//a.c 主程序源代码 #include <stdio.h> #include "b.h" main(){ bb(); } //b.h 主程序依赖b库,b库的头文件是b.h int a; void bb(void); //b.c b库源代码 #include <stdio.h> #include "b.h" int a=7; void bb(){ printf("das%d\n",a); }
首先生成动态库:
第一步:生成b.o目标文件,使用如下命令。在此处需要添加-fPIC参数,该参数用于生成位置无关代码已工生成动态库使用,使用命令:gcc -c -o b.o -fPIC b.c
第二步:使用-shared参数生成动态库,使用如下命令:gcc -shared -o libb.so b.o,
不过上述两部可以连在一起,:gcc -shared -fPIC -o libb.so b.c
接下来就是将程序文件a.c链接动态库生成二进制可执行程序的过程了,这里有很多方法:
方法一:如果将libb.so移动到/lib64;/usr/lib64;这两个任意目录下,直接用命令gcc -o a a.c -lb,则链接成功,
但是不提倡用这个方法,因为是我们自己编写的库文件,/lib;/usr/lib64这两个文件夹下都是些系统的库文件,所以还是不要碰这两个文件夹了
方法二:我们先在本地目录下生成动态库文件,然后将本目录加入到系统搜索动态库文件的环境变量LD_LIBRARY_PATH中(export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH)(事实上动态库的环境变量不只这一个,还有LD_PRELOAD,详见其他博客),然后再执行gcc -o a a.c -L. -lb
方法三,指定动态文件的位置,比如gcc -o a a.c /root/libb.so;gcc -o a a.c ./libb.so
一旦指定了动态文件的位置,动态文件将不能移动。以下通过gcc -o a a.c ./libb.so举例(我本人推荐此方法):
gcc -o a a.c ./libb.so
在方法三中,链接时已经明确了动态库的位置,所以如果移动动态库,甚至将动态库移动至/lib64目录下,或者将主程序a移动至其他目录,都将导致程序运行失败,只要保证动态库与可执行程序保持在同一文件夹下才有效