为什么要从.o创建.a文件进行静态链接?

pou*_*def 21 c linux gcc static-linking

考虑以下代码:

one.c:

#include <stdio.h>

int one() {
   printf("one!\n");
   return 1;
}
Run Code Online (Sandbox Code Playgroud)

two.c:

#include <stdio.h>

int two() {
   printf("two!\n");
   return 2;
}
Run Code Online (Sandbox Code Playgroud)

prog.c中

#include <stdio.h>

int one();
int two();

int main(int argc, char *argv[]) 
{
   one();
   two();

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想将这些程序链接在一起.所以我这样做:

gcc -c -o one.o one.c
gcc -c -o two.o two.c
gcc -o a.out prog.c one.o two.o
Run Code Online (Sandbox Code Playgroud)

这很好用.

或者我可以创建一个静态库:

ar rcs libone.a one.o
ar rcs libtwo.a two.o
gcc prog.c libone.a libtwo.a
gcc -L. prog.c -lone -ltwo
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:为什么我会使用第二个版本 - 我创建了一个".a"文件 - 而不是链接我的".o"文件?它们似乎都是静态链接,所以它们之间是否有优势或架构差异?

CB *_*ley 42

通常,库是可以在多个程序中使用的目标文件的集合.

在你的例子中没有任何优势,但你可能已经做到了:

ar rcs liboneandtwo.a one.o two.o
Run Code Online (Sandbox Code Playgroud)

然后链接您的程序变得更简单:

gcc -L. prog.c -loneandtwo
Run Code Online (Sandbox Code Playgroud)

这真的是一个包装问题.您是否有一组自然形成一组相关功能的目标文件,可以在多个程序中重复使用?如果是这样,那么他们可以合理地存档到静态库中,否则可能没有任何优势.

最终的链接步骤有一个重要的区别.您链接的任何目标文件都将包含在最终程序中.仅当库中的目标文件有助于解析其他目标文件中的任何未定义符号时,才会包含它们.如果他们不这样做,他们将不会链接到最终的可执行文件.


Unc*_*leO 12

不同之处在于可执行文件的大小,尽管可能不适用于您的示例.

链接到库时,只包含可执行文件使用的位.链接目标文件时,您可以完成整个过程.

例如,如果您的可执行文件必须在数学库中包含每个数学函数时只使用一个数学函数,那么它将比它需要的大得多,并且包含大量未使用的代码.

将其与Windows的动态链接模型进行对比很有意思.在那里,操作系统必须完全加载您的可执行文件使用的所有Dll(动态链接库),这可能导致RAM中的膨胀.这种模型的优点是您的可执行文件本身较小,并且链接的Dll可能已经在某些其他可执行文件使用的内存中,因此不需要再次加载它们.

在静态链接中,为每个可执行文件单独加载库函数.