C陷阱与缺陷 第4章 链接 4.1 什么是链接器

    链接器 
    一个C程序可能是由多个分别编译的部分构成,这些不同部分通过一个通常叫做链接器(也叫链接编辑器,或载入器)的程序合并成一个整体。因为编译器一般每次只处理一个文件,所以它不能检测出那些需要一次了解多个源程序文件才能察觉的错误。此外,在许多系统中链接器是独立于C语言实现的,因此,如果前述错误的原因是与C语言相关的,链接器对此同样束手无策。
    某些C语言实现提供了一个称为lint的程序,可以捕获到大量的此类错误,但遗憾的是并非所有的C语言实现都提供了该程序。如果能够找到诸如lint的程序,就一定要善加利用,这一点无论怎么强调也不为过。

    什么是链接器
    C语言中的一个重要思想就是分别编译(separate compilation),即若干源程序可以在不同的时候单独进行编译,然后在恰当时候整合到一起。但是,链接器一般是与C编译器分开的,它不可能了解C语言的诸多细节。那么,链接器是如何做到若干个C源程序合并成一个整体呢?尽管链接器并不理解C语言,然而它却能够理解机器语言和内存布局。编译器的责任是把程序“翻译”成对链接器有意义的形式,这样链接器就能够“读懂”C源程序了。

    典型的链接器把由编译器或汇编器生成的若干个目标模块,整合成一个被称为载入模块或可执行文件的实体---该实体能被操作系统直接执行。其中,某些目标模块是直接作为输入提供给链接器的;而另外一些目标模块则是根据链接过程的需要,从包括有类似printf函数的库文件中取得的。
    链接器通常把目标模块看成是由一组外部对象(external object)组成的。每个外部对象代表机器内存中的某个部分,并通过一个外部名称来识别。因此,程序中的每个函数和每个外部变量,如果没有声明为static,就都是一个外部对象。某些C编译器会对静态函数和静态变量的名称做一定改变,将它们也作为外部对象。由于经过了“名称修饰”,因此它们不会与其他源程序文件中的同名函数或同名变量发生命令冲突。

    大多数链接器都禁止同一个载入模块中的两个不同外部对象拥有相同的名称。链接器的一个重要工作就是处理这类命名冲突。

    处理命名冲突最简单的办法就是干脆完全禁止。对于外部对象是函数的情形,这种做法当然正确,一个程序如果包含两个同名的不同函数,编译器根本就不应该接受;而对于外部对象是变量的情形,不同的链接器对这种情况有着不同的处理形式。

    链接器的输入是一组目标模块和库文件。链接器的输出是一个载入模块。链接器读入目标模块和库文件,同时生成载入模块。对每个目标模块中的每个外部对象,链接器都要检查载入模块,看是否有同名的外部对象。如果没有,链接器就将该外部对象添加到载入模块中;如果有,链接器就要开始处理命名冲突。

    除了外部对象,目标模块还可能包括了对其他模块中的外部对象的引用,例如,一个调用了函数printf的C程序所生成的目标模块,就包括了一个对函数printf的引用。可以推测得出,该引用指向的是一个位于某个库文件中的外部对象。在链接器读入一个目标模块时,它必须解析出这个目标模块中定义的所有外部对象的引用,并做出标记说明这些外部对象不再是未定义的。

    如果读者的C语言实现中提供了lint程序,切记要使用!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_40186813

你的能量无可限量。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值