繁体   English   中英

为什么简单的程序会占用这么多存储空间?

[英]Why do simple programs take up so much storage space?

我在 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! )我只计算了完整的零块。

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

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

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

$ 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" ,并且每个部分都有一堆元数据。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM