分别编译与链接(Linking)
大多数高级语言都支持分别编译,程序员可以显式地把程序划分为独立的模块或文件,然后每个独立部分分别编译。在编译之后,由链接器把这些独立的片段(称为编译单元)“粘接到一起”。(想想这样做有什么好处?)
在C/C++中,这些独立的编译单元包括obj文件(一般的源程序编译而成)、lib文件(静态链接的函数库)、dll文件(动态链接的函数库)等。
静态链接方式:在程序执行之前完成所有的组装工作,生成一个可执行的目标文件(EXE文件)。
动态链接方式:在程序已经为了执行被装入内存之后完成链接工作,并且在内存中一般只保留该编译单元的一份拷贝。
- 静态链接
- 特点:在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。因此,链接器需要知道参与链接的目标文件需要哪些函数,同时也要知道每个目标文件都能提供什么函数,这样链接器才能知道是不是每个目标文件所需要的函数都能正确地链接。如果某个目标文件需要的函数在参与链接的目标文件中找不到的话,链接器就报错了。目标文件中有两个重要的接口来提供这些信息:一个是符号表,另外一个是重定位表。
- 优点:在程序发布的时候就不需要的依赖库,也就是不再需要带着库一块发布,程序可以独立执行。
- 缺点:
-
- 程序体积会相对大一些。
- 如果静态库有更新的话,所有可执行文件都得重新链接才能用上新的静态库。
- 动态链接
- 特点: 在编译的时候不直接拷贝可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统,操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库可执行代码,最终达到运行时连接的目的。
- 优点: 多个程序可以共享同一段代码,而不需要在磁盘上存储多个拷贝。
- 缺点: 由于是运行时加载,可能会影响程序的前期执行性能。
- 库
上面的文章多次提到库(lib)这个概念,所谓的库就
是一些功能代码经过编译连接后的可执行形式。
大家在Windows平台上见到的.dll文件和linux平台下so动态库都输入库。
库也有静态lib和动态lib之分:
-
-
- 静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序。
- 动态lib相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时候需要相应的dll文件支持。
- =================== 总 结 ============================
- 静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。但是若使用DLL,该DLL不必被包含在最终的EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
- 采用动态链接库的优点:(1)更加节省内存;(2)DLL文件与EXE文件独立,只要输出接口不变,更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性。
- 附录:Linux下的静态链接和动态链接:http://blog.chinaunix.net/uid-24532607-id-3082314.html