静态库 动态库 静态链接 动态链接 编译器cl.exe 链接器link.exe

来源:互联网 发布:samorost 3 mac 编辑:程序博客网 时间:2024/05/28 06:06

静态(链接)库lib:是一个或者多个obj文件的打包(包括函数和数据、实际执行代码、符号表),是在编译的时候加进程序的,在运行时不用加载库,在运行时对库没有依赖性。 

动态(链接)库dll:是在链接的时候加进程序的。动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。

导入库lib:动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。(how:导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。)

导入库+动态库:这也是实际上很多开源代码发布的惯用方式:1. 预编译的开发包:包含一些.dll文件和一些.lib文件。其中这里的.lib就是导入库,而不要错以为是静态库。但是引入方式和静态库一样,要在链接路径上添加找到这些.lib的路径。而.dll则最好放到最后产生的应用程序exe执行文件相同的目录。这样运行时,就会自动调入动态链接库。

静态链接:

Visual C++的编译器在链接过程中将从静态库中恢复这些函数和数据并把他们和应用程序中的其他模块组合在一起生成可执行文件。这个过程称为"静态链接",此时因为应用程序所需的全部内容都是从库中复制了出来,所以静态库本身并不需要与可执行文件一起发行。

动态链接:

 动态链接与静态链接的不同之处在于它允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。


拿程序调用动态库来说:

1 预处理: 宏替换、include展开等

2 编译:每个.cpp分别编译成.obj文件。obj文件中记录各个符号名,包括当前cpp能确定地址的符号名、将来链接时工程中其他cpp文件来确定地址的符号、运行装在时才能确定地址的调用dll中的符号。

           编译过程是:编译器先查找函数名、变量名定义或声明是否存在,先查找当前cpp定义、再到include进来的里面找(预处理后include里的函数声明也在此cpp中),所以动态库的导出函数必须在其头文件声明,需要用到dll的程序要include动态库头文件。都存在就翻译成符号。三个地方都找不到的就报编译错误。最后生成.obj.(至于obj中还包含什么信息,没有深入研究,不妨碍理解编译过程大框架)

          

3 链接:把对应库函数的引用用目标代码替换,然后把工程的多个.obj链接成一个exe。链接做的工作:把各个obj中的符号表弄到一个大的符号表中。再次把能确定地址的地址填上,涉及到地址重定位,之前每个obj中符号地址都是相对于自己文件的虚拟地址,现在从定位到整个exe的虚拟地址。存在一个找符号的地址过程,查找其他obj符号表,以及动态库的lib(导出符号表),找到的话,就把符号地址填上,dll此时还是没有地址,它直到加载才有地址,此时lib库的作用就是让编译器直到这个符号在dll中,运行时再确定。找不到的话就报连接错误。

4 运行:双击生成的exe,操作系统的装载器就把exe和dll装载到内存,这时,exe中调用动态库的符号的地址就确定了。动态库的dll中就保存有符号偏移、函数体、数据等信息。


程序调用静态库:

1 预处理和编译过程是相同的,所以使用静态库也需要include静态库头文件。

2 由于静态库的lib保存有符号偏移、函数体、数据等信息(不同于动态库的lib)。所以链接阶段就可以确定所有符号的地址了。链接的时候就是把各个obj和静态库的代码段、数据段等合并在一起,符号表完善地址(此时调用的函数代码区加载了,函数地址就确定了)。

动态库:动态链接库(Dynamic Link Library)是一个可以被其它程序共享的程序模块,其中封装了一些可以被共享的数据、函数和资源。
          如果一个可执行程序使用了一个DLL,当可执行程序运行时,操作系统会把DLL加载到内存,并解析可执行程序对该DLL的符号引用,使得可执行程序能够调用DLL中的函数功能。
          扩展名一般是dll(so),也有可能是fon、ocx、drv、sys(ko)等。DLL中虽然包含了可执行代码却不能单独执行,而应由其他应用程序直接或间接调用。

动态库:

静态库、动态库的共享问题:动态库所谓的内存共享内存中只加载一份,多个进程(程序)共享。静态库是调用的进程中都有一份,融合在各自的exe中。注意一个程序中每个有调用静态库函数obj都有一份静态库的内容。

老师课件内容:

链接器的主要工作

1 将分散的数据和机器代码收集并合成一个单一的可加载并可执行的文件;
2 符号解析:由多个程序模块(源程序)构建一个可执行程序时,模块之间的相互引用通过符号进行。程序也可以通过符号来引用代码库(lib库)中的功能。符号解析就是将符号引用和符号定义关联起来。
3 地址重定位:编译器产生的各个目标文件(obj文件)中数据和代码的地址一般都是从0开始。因此如果一个程序包含多个目标文件时就会产生地址重叠。重定位就是为每个目标文件重新定义加载地址,并修改相应的代码和数据以反映这种变化。

静态链接方式:在程序执行之前完成所有的组装工作,生成一个可执行的目标文件(如Windows下的EXE文件)。
动态链接方式:在程序已经为了执行被装入内存之后完成链接工作,并且在内存中一般只保留该编译单元的一份拷贝。
将函数名称和函数执行体动态链接(或动态绑定)的过程既可以发生在程序装载时,也可以发生在程序运行时(在需要时才会引入函数的方式)

预编译的函数库:模块化、可重用性强、编译速度快、保护知识产权
静态库(.a后缀)是一系列的目标文件的归档,静态链接时,静态库中的目标函数体会被复制到程序的可执行文件中去
动态库(libname.so[.major.minor.release])不具有“复制”操作,程序运行时根据需要载入内存,且动态地将函数调用与函数体关联到一起。动态库在内存中只有一份拷贝,因此也称为共享库。易于升级。

可以将静态链接库或动态链接库看成是一种仓库,它提供给你一些已经编译成机器代码的可以直接拿来用的数据、函数或类,它们是实现代码共享的一种方式。
 静态链接库中的机器代码和数据都被直接包含在最终生成的EXE文件中
动态链接库的内容不必被包含在最终的EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。

0 0
原创粉丝点击