我有一个在 Windows 上使用 MSVC 创建的静态库 *.lib。库的大小为 70KB。然后我有一个链接该库的应用程序。但现在最终可执行文件 (*.exe) 的大小为 29KB,小于库。我想知道的是:

  1. 由于该库是静态链接的,我认为它应该直接添加到可执行文件大小,并且最终的exe大小应该大于这个值?Windows exe 格式是否也对二进制数据进行一些压缩?

  2. Linux 系统情况如何,即 Linux 上的库大小(*.a/*.la 文件)与 Linux 可执行文件(*.out)的大小有何关系?

-广告

有帮助吗?

解决方案

中还有额外的簿记信息 .lib 最终可执行文件不需要的文件。此信息有助于链接器找到实际链接的代码。此外,调试信息可以存储在 .lib 文件但不在 .exe 文件(我不记得 lib 文件中 obj 的调试信息存储在哪里,它可能在其他地方)。

其他提示

Windows 和 Unix 上的静态库都是 .obj/.o 文件的集合。链接器查看每个目标文件并确定程序是否需要链接。如果不需要,则目标文件将不会包含在最终的可执行文件中。这可能会导致可执行文件比库小。

编辑:正如 MSalters 指出的,在 Windows 上,VC++ 编译器现在支持生成启用函数级链接的目标文件,例如,请参阅 这里. 。事实上,编辑并继续需要这样做,因为编辑并继续需要能够替换可执行文件的最小可能部分。

静态库可能包含几个从未使用过的函数。当链接器将库与主可执行文件链接时,它发现某些函数从未被使用(并且它们的地址从未被获取并存储在函数指针中),它只是丢弃代码。它还可以递归地执行此操作:如果函数 A() 从未被调用,并且 A() 调用 B(),但从未以其他方式调用 B(),则它可以删除 A() 和 B() 的代码。在 Linux 上,同样的事情也会发生。

免责声明:自从我处理静态链接以来已经很长时间了,所以请对我的回答持保留态度。

你写了: 我在想它应该直接添加到可执行文件大小,而最终的 exe 大小应该大于这个值?

天真的链接器正是这样工作的——当我为 CP/M 系统进行业余爱好开发时(很久以前),这是一个真正的问题。

然而,现代链接器更加智能 - 它们仅链接原始代码引用的函数或根据需要链接。

除了当前的答案之外,如果函数定义具有相同的目标代码,则允许链接器删除它们 - 这旨在帮助减少模板化代码的膨胀效应。

静态库必须包含 每一个 符号在其源代码中定义,因为它 可能 链接到只需要该特定符号的可执行文件。但是,一旦将其链接到可执行文件中,我们就可以准确地知道哪些符号最终被使用,哪些符号没有被使用。因此链接器可以轻松删除未使用的代码,从而大大减少文件大小。同样,任何重复的符号(在静态库及其链接的可执行文件中定义的任何内容)都会合并到单个实例中。

@全部:感谢您的指点。@Greg Hewgill - 你的回答是一个很好的指示。谢谢。

我查到的答案如下:

1.)在库构建过程中,如果MSVC(或类似的东西)中的“保留程序调试数据库”选项处于打开状态,则库的调试信息将使其大小膨胀。但是当我静态包含该库并创建可执行文件时,链接器会在生成 exe 之前从库中删除所有调试信息,因此 exe 大小小于库的大小。

2.)当我禁用“保留程序调试数据库”选项时,我得到的库的大小小于最终的可执行文件,我认为这在大多数情况下是正常的。

-广告

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top