【问题标题】:Why do simple programs take up so much storage space?为什么简单的程序会占用这么多存储空间?
【发布时间】:2021-02-18 13:14:06
【问题描述】:

我用 C 语言创建了一个简单的 hello world 程序,如下所示:

#include <stdio.h>

int main() {
    printf("Hello World!\n");
    return 0;
}

之后,我在 Mac 上使用 gcc 编译它并使用 xxd 转储它。每行 16 个字节(8 个字),编译后的程序总共有 3073 行或 49424 个字节。在所有这些字节中,只有 1 904 个字节组成了程序,而其余 47 520 个字节全为零。 考虑到只有大约 3.9% 的字节不是零,这是一个明显的空间浪费示例。有没有办法在这里优化可执行文件的大小? (顺便说一句,我已经尝试过使用-Os 编译器选项,但没有得到任何结果。)

编辑:我通过计算 hexdump 的行数得到了这些数字,但在包含实际指令的行中也有零。我没有计算这些字节,因为它们可能对程序的执行至关重要。 (就像字符串 Hello World! 的空终止符)我只计算了完整的零块。

【问题讨论】:

  • @Gerhardh 抱歉,我的意思是每行 16 个字节。 8个字。文件的大小也与 49 424 字节相匹配。
  • 只有#include &lt;stdio.h&gt; 怎么样?
  • 可执行文件具有依赖于系统的固定结构。不确定 Mac 上的 gcc,但由于底层系统是 Darwin,它是 BSD 的衍生产品,我会假设 elf。众所周知,elf 格式会生成大文件。但我记得 MS/DOS 系统上的 .com 文件要简洁得多:一个 256 字节的标头,后面是原始机器代码。可执行文件的较大部分是标准库,但使用汇编时,Hello world 程序的长度可能不到 300 字节...
  • 这么多臃肿,这么少时间......
  • muppetlabs.com/~breadbox/software/tiny/teensy.html 逐步构建一个 45 字节的可执行文件。

标签: c compiler-construction


【解决方案1】:

生成的文件不仅仅包含程序所需的代码和数据。它还包含正确加载和执行程序所需的元数据。一般来说,这个元数据可能会被分成多个部分,每个部分都需要在某个边界对齐。为了做到这一点,可以添加一些零来填充。对更大的程序进行相同的检查将减少元数据和填充占用的空间。

【讨论】:

    【解决方案2】:

    MacOS 上的 gcc 以 Mach-O 文件格式生成对象和可执行文件。该文件分为多个段,每个段都有一些对齐要求,以提高加载效率(因此你得到所有的零填充)。我拿了你的代码并用 gcc 在我的 Mac 上构建了它,给了我一个 8432 字节的可执行文件大小。是的,xxd 给了我一堆零。这是部分标题的objdump 输出:

    $ objdump -section-headers hello
    
    hello:  file format Mach-O 64-bit x86-64
    
    Sections:
    Idx Name          Size      Address          Type
      0 __text        0000002a 0000000100000f50 TEXT 
      1 __stubs       00000006 0000000100000f7a TEXT 
      2 __stub_helper 0000001a 0000000100000f80 TEXT 
      3 __cstring     0000000f 0000000100000f9a DATA 
      4 __unwind_info 00000048 0000000100000fac DATA 
      5 __nl_symbol_ptr 00000010 0000000100001000 DATA 
      6 __la_symbol_ptr 00000008 0000000100001010 DATA 
    

    __text 包含程序的机器码,__cstring 包含文字 "Hello World!\n",并且每个部分都有一堆元数据。

    对于像你这样的简单程序来说,这种结构显然是矫枉过正,但像你这样的简单程序不是常态。对象和可执行文件格式必须能够支持动态加载、符号重定位和其他需要复杂结构的东西。任何已编译的程序都存在最低程度的复杂性(以及大小)。

    因此,“小”程序的可执行文件比您认为的基于源代码的要大,但要意识到其中不仅仅是您的源代码。

    【讨论】:

      【解决方案3】:

      可执行文件也可能被制作为快速加载到内存中。特别是文本和数据段可以与操作系统的页面大小对齐。这通常是 4KB 甚至更大的 2 次方。在您称某事为浪费空间之前,请确保您了解链接编辑和加载、段以及 Executable and Linkable Format (ELF) 的所有复杂性。

      【讨论】:

        猜你喜欢
        • 2013-12-03
        • 2012-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-01
        • 1970-01-01
        相关资源
        最近更新 更多