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



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

#include <stdio.h>
int main() {
printf("Hello World!n");
return 0;
}

之后,我在Mac上使用gcc编译它,并使用xxd转储它。每行16字节(8个字),编译后的程序总共有3073行或49 424字节。在所有这些字节中,只有1904个字节组成了程序,而其余的47520个字节都是零。考虑到只有大约3.9%的字节不是零,这显然是浪费空间的一个例子。这里有什么方法可以优化可执行文件的大小吗?(顺便说一下,我已经尝试使用-Os编译器选项,没有得到任何结果。)

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

gcc在MacOS上以Mach-O文件格式生成对象和可执行文件。文件被分成多个段,每个段都有一些对齐要求,以使加载更有效(因此您得到所有零填充)。我拿了你的代码,用gcc在我的Mac上构建它,给我一个8432字节的可执行文件。是的,xxd给了我一堆0。下面是部分报头的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",每个部分都有一堆元数据。

对于像您这样的简单程序来说,这种结构显然是多余的,但是像您这样的简单程序并不是标准的。对象和可执行文件格式必须能够支持动态加载、符号重定位和其他需要复杂结构的东西。任何编译后的程序都有一个最小的复杂度(以及最小的大小)。

所以可执行文件为"small"基于源代码的程序比你想象的要大,但要意识到其中不仅仅是源代码。

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

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

相关内容

最新更新