gcc中的-l选项问题:链接库的顺序问题--明明包含了库却报“undefined reference“

我正在尝试编译使用udis86库的程序。实际上,我使用的是库user-manual中提供的示例程序。但是在编译时会产生错误。我得到的错误是:

example.c:(.text+0x7): undefined reference to 'ud_init'
example.c:(.text+0x7): undefined reference to 'ud_set_input_file'
.
.
example.c:(.text+0x7): undefined reference to 'ud_insn_asm'

我正在使用的命令是:

$ gcc -ludis86 example.c -o example

按照用户手册中的说明进行操作。
显然,链接器无法链接libudis库。但是,如果我将命令更改为:

$ gcc example.c -ludis86 -o example

它开始工作。因此,能否请有人解释第一个命令的问题是什么?

最佳答案

因为这就是GNU链接器使用的链接算法的工作方式(至少在链接静态库时)。链接器是一个单通道链接器,一旦看到它们就不会重新访问库。

库是目标文件的集合(归档)。使用-l选项添加库时,链接器不会无条件地从库中获取所有目标文件。它仅采用当前所需的那些目标文件,即解析一些当前未解析(待定)符号的文件。之后,链接器完全忘记了该库。

当链接器处理输入的目标文件时,链接器会不断维护挂起的符号列表。在处理每个目标文件时,一些符号将被解析并从列表中删除,其他新发现的未解析的符号将被添加到列表中。

因此,如果使用-l包含了某些库,则链接程序将使用该库来解析尽可能多的当前暂挂符号,然后完全忽略该库。如果以后突然发现它现在需要该库中的一些其他目标文件,则链接程序将不会“返回”该库以检索那些其他目标文件。已经为时已晚。

因此,在链接器命令行的后期使用-l选项始终是一个好主意,这样,当链接器到达该-l时,它可以可靠地确定所需的对象文件和不需要的对象文件。不需要。将-l选项作为链接器的第一个参数通常根本没有任何意义:一开始,待处理符号列表为空(或更确切地说,由单个符号main组成),这意味着链接程序根本不会从库中获取任何内容。

在您的情况下,您的目标文件example.o包含对符号ud_initud_set_input_file等的引用。链接器应首先接收该目标文件。它将这些符号添加到未决符号列表中。之后,您可以使用-l选项添加您的库:-ludis86。链接器将搜索您的库并从中获取所有解析那些未决符号的内容。

如果在命令行中首先放置-ludis86选项,则链接器将有效地忽略您的库,因为在开始时它不知道它将需要ud_initud_set_input_file等。稍后,在处理example.o时它将发现这些符号并将它们添加到挂起的符号列表中。但是这些符号将一直无法解析到最后,因为-ludis86已经被处理(并有效地被忽略了)。

有时,当两个(或多个)库以循环方式相互引用时,甚至可能需要对同一库使用两次-l选项,以使链接程序有两次机会从该库中检索必要的对象文件。

关于c - 为什么gcc中'-l'选项的顺序很重要?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39716940/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值