C静态库如何工作?

时间:2016-01-06 16:54:31

标签: c gcc module static-libraries

使用库时,最终可执行文件中包含哪些代码?

<小时/> 例如,我们有两个文件:

/*main.c*/
int main (int argc, char* argv[]){
    fc(1); /*This function is defined in fc.c*/
}

另一个档案:

/*fc.c*/
int fc(int x){
    return fe(x);
}
int fe(int y){
    return y + 1;
}

我们编译fc.c:

  

gcc -c fc.c

然后我们得到fc.o。

现在让我们构建一个名为test的库:

  

ar rcs libtest.a fc.o

我们现在有libtest.a。

现在我们编译main.c

  

gcc -c main.c

我们获得main.o

让我们将main.o链接到我们的libtest.a

  

gcc -L。 main.o -ltest

我们得到了理想的a.out

检查它的符号:

  

nm a.out

在所有符号之间,我们发现:

  

080483cc T fc
  080483df T fe

似乎很好。 但是!

如果我们的main.c改变了吗?

/*main.c*/
int main (int argc, char* argv[]){
    fe(1); /*This function is defined in fc.c*/
}

在编译main.c并将新的main.o链接到我们的库之后,我仍然会找到fc的符号。但我不需要那个代码。

问题

- 图书馆不能“只给我”main.c中需要的代码吗? - 在添加到库之前,功能是否需要在单独的模块中? - 如果我有300个功能怎么办?我需要制作300个模块吗?

2 个答案:

答案 0 :(得分:2)

是的,将每个功能放在一个单独的模块中。这样,链接器将仅链接所需的项目。

答案 1 :(得分:1)

简而言之,有一些编译器标志可以从最终的可执行代码中删除未使用的函数,但默认情况下它们不会启用。

GCC可以做到这一点&#34;垃圾收集&#34;如果添加了这些标志,则使用未使用的函数:

  1. -ffunction-sections作为编译时标志。它指示编译器为每个函数创建单独的部分(请参阅object file format)。还有-fdata-sections标志,其含义与变量相似。

  2. -Wl,--gc-sections作为链接时标志。 -Wl部分指示GCC将以下选项传递给链接器。 --gc-sections表示&#34;垃圾选择部分,所有代码都从其中取消&#34;。由于编译时选项,每个函数都有一个单独的部分,它有效地执行功能级修剪。