链接顺序问题

8 篇文章 0 订阅

链接是基于对象文件和对象文件库构建可执行文件的过程。链接的基本思想是将每个已解析的符号与其对应的定义关联起来。这个过程也成为符号解析。

链接器将已解析和未解析的符号保存在两个列表中。链接器的主要工作就是在将对象文件和库汇编成程序时,把未解析符号转换为已解析的符号。在最后的可执行程序中,每个符号都必须有一个有效的定义,否则就会出现问题。

解析未定义的符号

最常见的链接问题就是由未解析的符号引起的。

1 丢失链接器参数

如果链接器的命令行参数中丢失了某个对象文件,而它当中包含所需要的符号定义,那么链接器将报告丢失的符号。

2 搜索丢失的符号

根据项目规模的不同,查找丢失的符号定义可能非常困难。在最好的情况下,程序员知道丢失了哪个符号以及它是在哪里定义的,不是在对象文件或库中,就是在某个仍需要编译的源文件中。

如果不知道符号或它的定义位置,那么第一个方法就是搜索它。如果符号是一个函数或方法,则应该试着在文档中查询它。好的搜索目标是计算机系统文档、项目文档或第三方软件的文档。或者用计算机来搜索。在UNIX上,可以使用实用程序grep和find来定位文件。在windows上,可以使用浏览器的搜索对话框。

有一些实用程序可以用来分析对象文件、库和程序中的符号。在UNIX上,实用程序nm提供了一个符号清单。在windows上,可以使用实用程序DUMPBIN。需要解析的符号用U或UNDEF来标记,而已定义的符号前面带有一个标记,用来指明包含符号定义的对象文件部分。例如,字母T对应对象文件的文本部分,也就是对已编译代码的说明部分。表示函数的符号包含在对象文件的文本部分中。

nm -o *.o | grep 要查的符号

nm显示了当前目录中所有对象文件中的符号的清单,而grep过滤出我们感兴趣的函数名称。使用nm的-o选项将文件名显示在行首,否则grep命令的结果就不是特别有用了。

如果项目的对象文件或库中均不含有丢失的符号,那么可以使用相同的策略在以下位置搜索定义。

1)在程序的源代码中。如果代码未被编译到对象文件中,则需要修复构建系统。

2)在系统库中。由于计算机上通常有大量的系统库,所以很容易查询联机文档。例如,如果在UNIX上有一个未定义的符号sqrtf,则man sqrtf命令将显示此函数在math库中,并且需要链接器参数-lm。

3)在第三方软件库中。如果程序中计划包含其他公司或开发人员的软件,则丢失的符号可能会在他们的软件库中找到。

4)在计算机或网络外部。如果系统定义所在的对象不在我们自己的系统上,则可能需要用因特网搜索引擎来查找丢失的库或符号。你可能会惊奇的发现很多程序员遇到并解决了与你同样的问题。

 

3 链接顺序问题

如果直接将对象文件作为链接器的参数来提供,那么它的所有符号都将被链接到最后的可执行文件中,这是一个重要方面。尤其是当链接那些包含各种服务函数(这些函数一般用于多个项目)的对象文件时,可能会得到我们不想要的结果,即产生了一个不必要的、过大的可执行文件。为了避免此问题,可以使用库或归档文件(archive file)来替代对象文件。链接器可以从库中挑选那些包含当前未定义符号的对象文件。要注意的重要一点是,大多数链接器对提供给它的对象文件和库只进行依次处理,在处理时依据以下算法。

首先,链接器载入对象文件,对象文件包含程序的初始化代码,初始化代码也调用C程序的main例程,也就是说,链接器至少以未定义的符号main开始。编译器驱动程序自动将包含初始化例程的对象文件提供给链接器。

然后,链接器按照链接行参数的顺序继续走查指定的对象文件和库,链接器从每个库中将那些至少包含一个未解析符号的对象文件挑选出来。它从对象文件中挑出所有符号,无论是否对链接器列表中标记为未定义的符号进行解析。当从新的对象文件载入链接器时,可能会产生新的未定义符号。

如果在链接行的结尾,所有符号均已解析,则链接过程成功。

有些时候,即使链接器所需的各部分信息都存在,仍然报告丢失了符号;这时可以考虑是否没有正确排序链接器参数

 

UNIX实用程序ar可以从对象文件.o生成库.a,是一个用来创建或修改库的程序,它还可以从库中提取对象。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小帆别吃糖

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值