• (进行)程序定义和引用符号(全局变量和函数)
  • 局部变量和参数等等经编译器处理后不再是符号
  • 符号定义存储在目标文件中(由汇编器)的符号表中.
    • 符号表示一个结构型的数组
    • 每个条目包括名称、大小和符号的位置.
  • 在符号解析步骤中,链接器将每个符号引用正好与一个符号定义关联起来

链接器解析符号引用的方法是将每个引用与它输入的可重定位目标文件的符号表中的一个确定的符号定义关联起来
编译器只允许每个模块中每个局部符号有一个定义
静态局部变量也会有本地链接器符号,编译器还要确保它们拥有唯一的名字

对全局符号的引用解析
当编译器遇到一个不是在当前模块中定义的符号(变量或函数名)时,会假设该符号是在其他某个模块中定义的,生成一个链接器符号表条目,并把它交给链接器处理
如果链接器在它的任何输入模块中都找不到这个被引用符号的定义,就输出一条(通常很难阅读的)错误信息并终止

链接器如何解析多重定义的全局符号

符号解析规则

链接器符号处理规则

全局符号分两种

强符号

  • 函数
  • 初始化的全局变量

弱符号

  • 未初始化的全局变量

规则一:不允许多个同名强符号

规则二:一个强符号和多个弱符号同名,选强(有强选强)

  • 对于弱符号的引用被解析为强符号,也就是把那些弱符号当做那个唯一的强符号使用

规则三:有多个弱符号,选择任意一个

  • gcc -fno-common 使多重定义弱符号链接时报错
  • gcc -Werror 警告变为错误,终止链接

两个同名弱符号,由不同的编译器来编译会采用不同的排列规则

对于全局变量

  • 能不用就不用
  • 如果要用
    • 用 static 定义在内部
    • 或者定义的时候初始化
    • 使用 extern 声明为引用的外部全局符号
Link to original