【问题标题】:How is object code copied into executable when linking against static library?链接静态库时如何将目标代码复制到可执行文件中?
【发布时间】:2012-10-09 13:56:14
【问题描述】:

我正在阅读 O'Reilly 的书 21st Century C,其中作者指出在链接静态库时:

编译器[有效地]将库的相关内容复制到最终的可执行文件中。

我试图通过创建我自己的包含此模块的静态库来测试这一点:

static char szStr[64];

char* single_func() {
    strcpy(szStr, "Hello string!\r\n");
    return szStr;
}

void func0() {
    strcpy(szStr, "Hello");
}

char* func1() {
    strcat(szStr, " string!\r\n");
    return szStr;
}

为了测试,我创建了两个 C 文件,其中一个调用 single_func(),另一个调用 func0()func1()

在这两种情况下,生成的可执行文件都是 751290B。如果我直接从模块中调用strcpystrcat,则两个可执行文件最终都是7215B。

这和上面的说法不冲突,还是我遗漏了一些关于链接的细节?

一个相关的问题是静态库是1600B,那么这个大小的增加是从哪里来的呢?


补充:

两个主文件都只包含调用函数并打印结果,如下所示:

main0:

#include <stdio.h>
#include "sharedlib.h"
int main() {
    char* szStr = single_func();
    printf("%s", szStr);
    return 0;
}

main1:

#include <stdio.h>
#include "sharedlib.h"
int main() {
    char* szStr;
    func0();
    szStr = func1();
    printf("%s", szStr);
    return 0;
}

文件是这样编译的:

gcc -static main0.c -L. -lsharedlib -o main0

平台是linux,编译器是gcc v4.6.3。

【问题讨论】:

    标签: c linker static-libraries


    【解决方案1】:

    对于静态库,复制的单位是库中的目标文件。由于您的两个程序都从目标文件中调用一个函数,因此两个程序都以可执行文件中的所有目标文件结束,因此大小相同(给定或取调用 main() 程序的大小)。

    可执行文件中的额外信息可能来自多个地方。其中一些将是控制和调试信息。如果您也静态链接它,其中一些可能来自 C 库。我们可能需要查看主程序和链接线,并了解平台以提出其他通货膨胀的原因。

    【讨论】:

    • 我已经用您要求的额外信息更新了我的问题,但我想我可以开始了解这是怎么回事。 1:当使用库的目标文件中的单个函数时,整个目标文件被滚动到可执行文件中。 2:通过使用 -static 选项 all 库被滚动到最终的可执行文件中,从而产生更大的文件大小。我说的对吗?
    • 是的;你在这两个细节上都是对的。如果您查看 Plauger 的书“标准 C 库”(针对 C89 标准),您会发现大多数源文件都有一个外部可见的功能,因此您不会将不使用的内容拖到可执行文件中。您可以通过在-lsharedlib 之后将-shared 添加到命令行来显着减小可执行文件的大小。
    • C 库正在(似乎正在)静态链接让我有点惊讶。有一次(也许是十年前)我认为 C 库不是作为静态库提供的(所以它必须被共享)。我可能记错了,或者它可能是在 Unix 变体而不是 Linux 上。您可以使用ldd main0 检查作为共享库加载的内容。它将列出使用的共享对象。
    • 当使用静态选项ldd main0 进行编译时,会给出“不是动态可执行文件”,因此 c 库似乎与它静态链接。我必须承认我没有检查过这个,就像你说的那样,我相信它不是静态版本的。使用 -shared 选项将文件大小降低到原始文件大小的十分之一,ldd main0 将 libc.so.6 列为链接库。谢谢您的帮助。非常感谢。
    • 我忘了提到要让它与动态链接的 libc 一起工作,你需要 -shared-libgcc 而不是 -shared。仅使用 -shared 会导致分段错误。
    猜你喜欢
    • 2011-02-28
    • 2018-04-13
    • 2015-04-16
    • 1970-01-01
    • 2013-06-24
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    相关资源
    最近更新 更多