链接器如何使用静态库来解析引用

创建静态链接库

创建Unix下的静态库 :

  1. gcc -c a.c b.c(想要合成静态库的c文件)
  2. ar rcs name.a a.o b.o(生成的静态库归档文件包含a.o、b.o,声明为name.a)

调用静态库:

  1. gcc -O2 -c main.c
  2. gcc -static -o p2 main.o ./name.a

这里链接器会根据main函数中具体调用了name.a库中的哪个函数(a.o、b.o)来将其中对应的a.o或b.o的内容复制校正到主文件中,而不是将整个name.a贴到里面。

解析引用的过程

Unix的链接器遵循从左到右的输入顺序来依次确定符号引用,即通过依赖关系。在这个过程中,链接器会维护一个可重定位目标文件集合E(这个集合中的文件就是确定的最后合并成可执行文件的模块文件),一个未解析(还未找到其定义但已经出现对其引用的)的集合U,以及一个已解析(前边文件已定义但未引用的)的集合D。

1.先判断命令行给出的输入文件是标准目标文件还是存档文件

  如果是目标文件,链接器会将这个文件添加到集合E,并根据该文件的符号引用情况修改集合U和D的元素状态,并继续下一个文件;

  如果是归档文件(.a文件),就根据集合U中的符号引用依次与存档文件中定义的符号对比匹配。如果某个存档文件中的成员m定义了U中的符号,就将m加入到E中,并根据m的符号,更新U和D——对整个存档文件重复这个过程直到U和D不再改变为止,其余都丢弃。继续下一个文件。

2.判断U的状态

  当所有文件处理完后,U非空,说明引用了未定义的符号,报错终止;

U空,则合并E中的目标文件。

输入文件顺序很重要

1.一般来说,应该是先目标文件,再归档文件。因为归档文件的添加要根据集合U来确定。放在前边因为U空,所以什么都不会添加,等到后边目标文件解析时就要出错了;

2.如果各个文件、库之间的引用关系是独立的,全部都是本地引用,则不用考虑顺序问题;

3.对于库与库之间,如果库调库,那么库之间也要注意顺序;甚至对于两个库之间的互相调用,为了满足依赖关系,还会出现重复归档文件的情况,如:

  gcc foo.c lib1.a lib2.a lib1.a

   这里lib1调用了lib2,而lib2又调用了lib1。

4.想要避免这种情况的话,可以将lib1、lib2两个库合成一个库。

猜你喜欢

转载自www.cnblogs.com/fusiji/p/11409748.html