📜  链接器如何解析在多个位置定义的全局符号?(1)

📅  最后修改于: 2023-12-03 14:58:13.966000             🧑  作者: Mango

链接器如何解析在多个位置定义的全局符号?

在进行程序的编译和链接时,全局符号(例如全局变量、函数)的定义可能散落在不同的源文件中。链接器负责将这些分散的定义整合起来,以便在运行时正确地解析和使用这些全局符号。

链接器通过符号表(Symbol Table)来管理和解析全局符号。符号表是一个包含了全局符号名称和对应地址的数据库。当链接器遇到一个全局符号的引用时,它会在符号表中查找该符号的定义,并将其地址信息填入引用处。下面是链接器解析多个位置定义的全局符号的一般步骤:

  1. 预处理:在编译过程中,预处理器会处理源代码中的宏定义、条件编译等指令,生成一个经过预处理的源文件。

  2. 编译:编译器将预处理后的源文件转换成目标文件,包含了代码和数据的二进制表示以及符号信息。目标文件中可能包含了未解析的全局符号引用,以及定义了的全局符号。

  3. 链接:链接器将多个目标文件组合在一起,解析和整合全局符号的定义和引用。链接器大致可以分为以下几个步骤:

    • 符号解析:链接器首先通过遍历所有目标文件,从中提取全局符号的信息,包括符号名称、类型、大小等,生成符号表。符号表是链接器解析和整合全局符号的核心数据结构。

    • 符号解析算法:链接器使用一种称为"单一定义规则"(One Definition Rule)的算法来解析多个位置定义的全局符号。该规则规定,一个全局符号在整个程序中只能有一个定义,否则就会产生冲突。该规则有多种变体,如C语言中的"强符号"和"弱符号"。

    • 符号解析过程:

      • 首先,链接器会遍历符号表,检查每个全局符号的定义和引用。
      • 对于每个未解析的全局符号引用,链接器会搜索整个符号表,查找对应的定义。
      • 如果找到了对应的定义,链接器会将引用处的符号地址更新为定义处的地址。如果找不到对应的定义,链接器会报告一个"未定义符号"错误。
    • 符号重定位:当链接器找到了所有未解析的符号引用的定义位置后,它将会进行地址重定位。即根据符号表中的定义地址,修改目标文件中的所有引用处的地址,使之指向正确的定义位置。

  4. 可执行文件生成:最后,链接器将解析和重定位后的目标文件生成可执行文件。可执行文件中包含了程序的二进制代码、数据,以及解析后的全局符号。

需要注意的是,链接器在解析多个位置定义的全局符号时,必须保证符号定义的一致性和唯一性。否则,会引发链接错误或运行时错误。因此,在进行程序开发时,应遵循良好的编程实践,避免在多个位置定义相同名称的全局符号。

参考文献: