我经常听到术语“静态链接”和“动态链接”,通常是指用C,C ++或C#编写的代码。他们是什么人,他们到底在说什么,他们有什么联系?
从源代码(您编写的内容)到可执行代码(您运行的内容)有两个阶段(在大多数情况下,对解释代码进行打折)。
首先是编译,它将源代码转换为目标模块。
第二个链接是将对象模块组合在一起以形成可执行文件的链接。
区别在于:允许第三方库包含在您的可执行文件中,而您无需查看它们的源代码(例如用于数据库访问,网络通信和图形用户界面的库),或用于编译不同语言的代码( C和汇编代码),然后将它们链接在一起。
当您将文件 静态 链接到可执行文件时,该文件的内容将在链接时包括在内。换句话说,文件的内容实际上已插入到将要运行的可执行文件中。
动态 链接时,可执行文件中将包含指向要链接的文件的指针(例如,文件的文件名),而链接时不包含该文件的内容。只有在以后 运行 可执行文件时,这些动态链接的文件才被购买,并且它们仅被购买到可执行文件的内存副本中,而不是磁盘上的副本。
基本上,这是一种延迟链接的方法。还有一个 更 延迟的方法(在某些系统上称为“后期绑定”),在您实际尝试在其中调用函数之前,不会引入动态链接的文件。
静态链接的文件在链接时被“锁定”到可执行文件,因此它们永远不会改变。可执行文件引用的动态链接文件仅通过替换磁盘上的文件即可更改。
这样就可以更新功能,而不必重新链接代码。每次运行时,加载程序都会重新链接。
这既有好处也有坏处-一方面,它允许更容易的更新和错误修复,另一方面,如果更新不兼容,则可能导致程序停止工作-这有时是造成某些人可怕的“ DLL地狱”的原因其中提到,如果用不兼容的库替换动态链接的库,应用程序可能会损坏(顺便说一下,这样做的开发人员应该被追捕并受到严厉的惩罚)。
作为 示例 ,让我们看一下用户编译main.c文件以进行静态和动态链接的情况。
main.c
Phase Static Dynamic -------- ---------------------- ------------------------ +---------+ +---------+ | main.c | | main.c | +---------+ +---------+ Compile........|.........................|................... +---------+ +---------+ +---------+ +--------+ | main.o | | crtlib | | main.o | | crtimp | +---------+ +---------+ +---------+ +--------+ Link...........|..........|..............|...........|....... | | +-----------+ | | | +---------+ | +---------+ +--------+ | main |-----+ | main | | crtdll | +---------+ +---------+ +--------+ Load/Run.......|.........................|..........|........ +---------+ +---------+ | | main in | | main in |-----+ | memory | | memory | +---------+ +---------+
在静态情况下,您可以看到主程序和C运行时库在链接时(由开发人员)链接在一起。由于用户通常无法重新链接可执行文件,因此他们被库的行为所困扰。
在动态情况下,主程序与C运行时导入库(声明动态库中的内容但未实际 定义的 内容)链接在一起。即使实际的代码丢失,这也允许链接器链接。
然后,在运行时,操作系统加载程序将主程序与C运行时DLL(动态链接库或共享库或其他命名法)进行后期链接。
C运行时的所有者可以随时插入新的DLL,以提供更新或错误修复。如前所述,这具有优点和缺点。