[英]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.