静态链接与动态链接的区别【转】
动态链接库、静态库、import库区别
动态链接库(Dynamic Linked Library):
Windows为应用程序提供了丰富的函数调用,这些函数调用都包含在动态链接库中。其中有3个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。
静态库(Static Library):
函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件(.EXE文件)。
导入库(Import Library):
在使用动态链接库的时候,往往提供两个文件:一个引入库和一个DLL。引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL,访问DLL中导出的函数。在运行Windows程序时,它通过一个被称作“动态链接”的进程与Windows相接。一个Windows的.EXE文件拥有它使用不同动态链接库的引用,所使用的函数即在那里。当Windows程序被加载到内存中时,程序中的调用被指向DLL函数的入口,如果DLL不在内存中,系统就将其加载到内存中。当链接Windows程序以产生一个可执行文件时,你必须链接由编程环境提供的专门的“导入库(import library)库”。这些导入库包含了动态链接库名称和所有Windows函数调用的引用信息。链接程序使用该信息在.EXE文件中构造一个表,当加载程序时,Windows使用它将调用转换为Windows函数。
静态库与导入库的区别:
导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。
静态链接与动态链接:
静态链接方法:#pragma comment(lib, "test.lib") ,静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来
静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库
动态链接方法:LoadLibrary()/GetProcessAddress()和FreeLibrary(),使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这种方式使程序初始化时间较短,但运行期间的性能比不上静态链接的程序。
在软件开发的过程中,大家经常会或多或少的使用别人编写的或者系统提供的动态库或静态库,但是究竟是使用静态库还是动态库呢?他们的适用条件是什么呢?
简单的说,静态库和应用程序编译在一起,在任何情况下都能运行,而动态库是动态链接,顾名思义就是在应用程序启动的时候才会链接,所以,当用户的系统上没有该动态库时,应用程序就会运行失败。再看它们的特点:
动态库:
1.共享:多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可;
2.开发模块好:要求设计者对功能划分的比较好。
静态库:代码的装载速度快,执行速度也较快,因为编译时它只会把你需要的那部分链接进去,应用程序相对比较大。但是如果多个应用程序使用的话,会被装载多次,浪费内存。
综上,我个人认为,如果你的系统上有多个应用程序都使用该库的话,就把它编译成动态库,这样虽然刚启动的时候加载比较慢,但是多任务的时候会比较节省内存;如果你的系统上只有一到两个应用使用该库,并且使用的API比较少的话,就编译成静态库吧,一般的静态库还可以进行裁剪编译,这样应用程序可能会比较大,但是启动的速度会大大提高。
**************************************
静态库链接时搜索路径顺序:
1. ld会去找GCC命令中的参数-L
2. 再找gcc的环境变量LIBRARY_PATH
3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的
动态链接时、执行时搜索路径顺序:
1. 编译目标代码时指定的动态库搜索路径
2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
4. 默认的动态库搜索路径/lib
5. 默认的动态库搜索路径/usr/lib
有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径
**************************************
在Linux下编译链接或运行c/c++程序时可能会遇到找不到头文件,找不到库文件的错误,简单总结一下这些错误的解决方法
1,找不到头文件
解决方法一:在编译时使用 -I 来指定头文件的路径,例如把头文件放在 /home/user/include/ 目录下,则在编译时加上 -I /home/user/include/ ,如有多个目录,可多次使用-I来指定
解决方法二:将头文件的路径加入环境变量CPATH中,如 export CPATH=" /home/user/include/",也可以根据情况使用下面的三个环境变量:
C_INCLUDE_PATH 编译C程序时使用的环境变量,用于查找头文件。
CPLUS_INCLUDE_PATH 编译C++程序时使用的环境变量,用于查找头文件。
OBJC_INCLUDE_PATH 编译Obj-C程序时使用的环境变量,用于查找头文件。
CPATH 编译C/C++/Obj-C程序时使用的环境变量,用于查找头文件。
2,链接时找不到库文件
解决方法一:在链接时使用-L参数来指定库的路径,例如把某个自己制作的动态库放在/home/user/lib/目录下了,则链接程序时加上-L/home/user/lib/,同时可以使用-l来指定库的名称,如指定线程库:-lpthread
解决方法二:把库文件放入系统的库文件目录下,如/lib,/usr/lib等,操作系统运行该程序时会自动到这些目录下找库文件
解决方法三:把库文件所在的目录加入LIBRARY_PATH环境变量中,如 export LIBRARY_PATH=" /home/user/lib/"
3,运行时找不到动态库
解决方法一:把库文件放入系统的库文件目录下,如/lib,/usr/lib等
解决方法二:把库文件所在的目录加入LD_LIBRARY_PATH环境变量中,如 export LD_LIBRARY_PATH=" /home/user/lib/"