- 1、本文档共13页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第 11章 高级技术
$Revision: 2.1 $
$Date: 1999/06/04 20:30:28 $
这一章描述了一些并不是在任何地方都适用的链接器技术。
C++的技术
C++对链接器来说存在三个明显的挑战。一个是它复杂的命名规则,主要在于如果多个
函数具有不同的参数类型则可以拥有相同的名称。name mangling 可以对他们进行很好的地
址分配,所有的链接器都使用这种技术的不同形式。
第二个是全局的构造和析构代码,他们需要在 main 例程运行前运行和 main 例程退出后
运行。这需要链接器将构造代码和析构代码片段(或者至少是指向它们的指针)都收集起来
放在一个地方,一边在启动和退出时将他们一并执行。
第三,也是目前最复杂的问题即模板和“extern inline”过程。一个 C++模板定义了
一个无穷的过程的家族,每一个家族成员都是由某个类型特定的模板。例如,一个模板可能
定义了一个通用的 hash 表,则就有整数类型的 hash 表家族成员,浮点数类型的 hash 表家
族成员,字符串类型的,或指向各种数据结构的指针的类型的。由于计算机的存储器容量是
无穷的,被编译好的程序需要包含程序中用到的这个家族中实际用到的所有成员,并且不能
包含其它的。如果 C++编译器采用传统方法单独处理每一个源代码文件,他不能确定是否所
编译的源代码文件中用到的模板是否在其它源代码文件中还存在被使用的其它家族成员。如
果编译器采用保守的方法为每一个文件中使用到的每一个家族成员都产生相应的代码,那么
最后将可能对某些家族成员产生了多分代码,这就浪费了空间。如果它不产生那些代码,它
就有漏掉某一个需要的家族成员的可能性存在。
inline 函数存在一个相似的问题。通常,inline 函数被像宏那样扩展开,但是在某些
情况下编译器会产生该函数相反的 out of line 版本。如果若干个不同的文件使用某个包含
一个 inline 函数的单一头文件,并且某些文件需要一个out of line 的版本,就会产生代
码重复的相同问题。
一些编译器采用改变源代码语言的方法以帮助产生可以被“哑”链接器(dump linker
s )链接的目标代码。很多最近的C++系统都把这个问题放到了首位,或者让链接器更聪明
些,或者将程序开发系统的其它部分和链接器整合在一起,以解决这个问题。下面我们概要
的看看后一种途径。
试验链接
对于使用“头脑简单”的链接器构建起来的系统,C++系统使用了多种技巧来使得C++
程序得以被链接。一种方法是先用传统的 C 前端实现来进行通常都会失败的试验链接,然后
让编译器驱动(运行各种编译器、汇编器、链接器代码片段的程序)从链接结果中提取信息,
再重新编译和连接以完成任务。图1
――――――――――――――――――――――――――――――――――――――――
Figure 11-1: Trial linking
input files pass through linker to trial output plus errors, then inputs
plus info from errors plus maybe more generated objects pass through linker to
final object
――――――――――――――――――――――――――――――――――――――――
在 UNIX系统上,如果linker在一次链接任务中不能够解析所有的未定义符号引用,他
可以选择仍然输出一个作为后续链接任务的输入文件的输出文件。在连接过程中链接器使用
普通的库查找规则,使得输出文件包含所需的库,这也是再次作为输入文件所包含的信息。
试验链接解决了上面所有的 C++问题,虽然很慢,但却是有效的方法。
对于全局的构造和析构代码,C++编译器在每一个输入文件中建立了完成构造和析构功
能的例程。这些例程在逻辑上是匿名的,但是编译器给他们分配了可识别的名称。例如,GN
U C++编译器会对名为 junk的类中的变量创建名为_GLOBAL_.I.__4junk和_GLOBAL_.D.__4ju
nk的构造例程及析构例程。在试验链接结束后,链接器驱动程序会检测输出文件的符号表
并为全局构造和析构例程建立一个链表,这是通过编写一个由数组构构成的队列的源代码文
件来实现的(通过C 或者汇编语言)。然后在再次链接中,C++的启动和退出代码使
文档评论(0)