静态链接时静态库的位置问题

静态链接时静态库的位置问题

笔记简述

在使用静态链接时,静态库在命令中的位置不恰当,将会导致链接错误。此问题之前在看《专业嵌入式软件开发》时有看到过。李云大佬只是在书中给出了一个他的经验例子,但是其根本原因当时并没有真正明白。今天在《CSAPP》的链接这一章节看到了对此问题的详细描述,所以记录下来。

正文

以《专业嵌入式软件开发》中所给的例子引出问题(P105图4.21)

// foo.c
#include <stdio.h>
void foo()
{
    printf("this is foo ()!\n");
}

// main.c
extern void foo();
int main()
{
    foo();
    return 0;
}

然后是编译,生成静态库以及链接的步骤:

# 生成可重定位目标文件
gcc -c foo.c -o foo.o
gcc -c main.c -o main.o

# 生成库文件
ar crs libfoo.a foo.o

# 链接
gcc -o a.out -L. -lfoo main.o

结果在链接的时候出错:
main.o: In function `main': main.c:(.text+0xa): undefined reference to `foo' collect2: error: ld returned 1 exit status

先给出解决办法以及结论:

关于库的一般准则是将他们放在命令行的结尾。如果各个库的成员是相互独立的,那么这些库就可以以任何顺序放置在命令行的结尾。另一方面,如果库不是相互独立的,那么必须对他们排序。

接下来给出对于这个问题的解释:

首先可以使用nm(符号显示器)来分别打印foo.o,main.o这连个模块中的符号:

ubuntu@ubuntu-lts:~/workspace/ld$ nm main.o
                 U _GLOBAL_OFFSET_TABLE_
                 U foo
0000000000000000 T main

ubuntu@ubuntu-lts:~/workspace/ld$ nm foo.o 
0000000000000000 T foo

可以看到在main.o模块中,foo这个符号是未定义的,在foo.o模块中,foo这个符号是定义了的且放在.text段中。
在这里插入图片描述

为什么当链接器的输入文件是库文件时,只会根据未解析符号集合U中的符号来进行匹配?

这个问题在《CSAPP》的链接这一章也有提到过,对于一个库文件来说,一般来说是很大的,例如libc.a文件:

ubuntu@ubuntu-lts:~/workspace/ld$ ls -l /usr/lib/x86_64-linux-gnu/libc.a 
-rw-r--r-- 1 root root 5477660 Apr 17  2018 /usr/lib/x86_64-linux-gnu/libc.a

可以看到其大小有5M左右,如果不根据“未解析符号集合U”来处理库文件中的符号,那么就不得不将库文件中的所有符号拷贝出来,但是库文件中的其他的很多的内容可能我们并不需要用到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值