《C专家编程》:对链接的思考

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/83926921

可执行程序产生的的流程

绝大多数编译器并不是一个单一的庞大程序。它们通常由多达六七个稍小的程序所组成,这些程序由一个叫“编译器驱动器”的控制程序来调用。这些可以方便的从编译器中分离的单独程序包括:预处理器、语法和语义检查器、代码生成器、汇编程序、优化器、链接器。

链接器

"a linker or link editor is a computer utility program that takes one or more object files generated by a compiler and combines them into a single executable file, library file, or another 'object' file."

链接器是一个将编译器产生的目标文件打包成可执行文件或者库文件或者目标文件的程序。

链接器的本质是一个程序,链接器的输入是编译器编译好的目标文件,链接器的输出是将目标文件打包处理后,生成可执行文件或者库或者目标文件

目标文件并不能直接执行,它需要载入到链接器中。链接器确认main函数为初始进入点(程序开始执行的地方),把符号引用绑定到内存地址,把所有的目标文件集中在一起,再加上库文件,从而产生可执行文件

可以将一个目标文件大致分为三段:数据段、代码段、符号表

链接器的一个主要任务就是符号决议

符号表给链接器提供了两种信息,一个是当前目标文件可以提供给其它目标文件使用的符号,另一个其它目标文件需要提供给当前目标文件使用的符号。有了这些信息链接器就可以进行符号决议了。链接器会依次扫描每一个给定的目标文件,同时链接器还维护了两个集合,一个是已定义符号集合D,另一个是未定义符合集合U,下面是链接器进行符合决议的过程:

  1. 对于当前目标文件,查找其符号表,并将已定义的符号并添加到已定义符号集合D中。
  2. 对于当前目标文件,查找其符号表,将每一个当前目标文件引用的符号与已定义符号集合D进行对比,如果该符号不在集合D中则将其添加到未定义符合集合U中。
  3. 当所有文件都扫描完成后,如果为定义符号集合U不为空,则说明当前输入的目标文件集合中有未定义错误,链接器报错,整个编译过程终止。

上面的过程看似复杂,其实用一句话概括就是只要每个目标文件所引用变量都能在其它目标文件中找到唯一的定义,整个链接过程就是正确的。

如果你觉得上面的解释比较晦涩的话,你也可以将链接符号决议这个过程想象成如下的游戏:

新学期开学后,幼儿园的小朋友们都带了礼物要和其它的小朋友们分享,同时每个小朋友也有自己的心愿单,每个小朋友都可以依照自己的心愿单去其它的小朋友那里拿礼物,整个过程结束后,每个小朋友都能拿到自己想要的礼物。

在这个游戏当中,小朋友就好比目标文件,每个小朋友自己带的礼物就好比每个目标文件的已定义符号集合,心愿单就好比每个目标文件中未定义符号的集合

静态链接与动态链接

静态链接在链接程序时需要使用的每个库函数的一份拷贝被加入到可执行文件中,即函数库的拷贝时可执行文件的物理组成部分

动态链接允许系统提供一个庞大的函数库集合,可以提供许多有用的服务。但是,程序将在运行时寻找他们,而不是把这些函数库的二进制代码作为自身可执行文件的一部分,在可执行文件里只是包含了文件名,让载入器在运行时能够寻找程序所需要的函数库,动态链接可执行文件比功能相同的静态链接可执行文件的体积小,所有动态链接到某个特定函数库的可执行文件在运行时共享该函数库的一个单独拷贝,动态链接是一种“Just-in-time”链接,这意味着程序在运行时必须能够找到它们所需要的函数库

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/83926921