我知道编译时包含在可执行文件中的代码可以来自目标文件(.o 文件)和静态链接库(.lib/.a 文件)。这两者在根本上和概念上有什么区别?为什么“目标代码”和“静态链接库”之间有不同的概念?每种方法的优点和缺点是什么,为什么要使用一种而不是另一种?静态链接库可以由目标文件制作,反之亦然,目标文件可以由静态链接库制作吗?
2 回答
目标文件是已编译但未链接的代码。库包含目标文件。因此,您的问题变成了“如果我只能使用目标文件,为什么还要使用静态链接的库?” 这就是为什么。
与对象集合不同,每个对象都有自己的符号表,库有一个统一的符号表,ar
由库开发人员使用s
开关调用时创建。 s
调用ranlib
为该存档中的所有对象创建统一的符号表。
在 shell 中运行ranlib
显示在帮助文本的第一行:
生成索引以加快对档案的访问。
并来自通用ranlib 文档:
具有这种索引的档案加快了与库的链接速度,并允许库中的例程相互调用,而无需考虑它们在档案中的位置。吨
另请参阅 FreeBSD ranlib 文档- 不同的措辞,相同的想法:链接速度。
库只是一个包含许多目标文件的文件,可以对其进行搜索以解析符号。
因此,通常,当您将对象链接在一起时,您会在一个可执行文件中获得所有对象(尽管一些优化链接器可能会丢弃未使用的对象)。
当您将库提供给链接器时,它会检查其中的每个目标文件并引入满足未解析符号所需的那些文件(并且可能会继续引入它们,直到所有符号都被解析或不再能够解析) .
这只是一种有效地将大量对象打包到一个文件中的方法,以便链接器可以完成更多工作——您不必担心需要哪些对象。
如果你想到 C 库,你可能会有一个printf.o
, puts.o
, ,fopen.o
因为你的源代码被很好地分开了。您不希望用户必须明确列出他们想要的每个目标文件,因此您将整个文件打包libc.a
并告诉他们他们只需要链接到该单个文件。
静态链接位在这里无关紧要,它只是决定对象应该在链接时进入可执行文件,而不是在运行时动态加载。这里解释了。