有没有理由甚至我最小的.c文件总是编译成至少128千字节的可执行文件?

时间:2016-01-13 03:08:48

标签: c compilation executable

我正在使用Dev-C ++,它使用GCC编译,在Windows 8.1,64位上。

我注意到我的所有.c文件总是编译成至少128千字节的.exe文件,无论源是多么小。即使是一个简单的“Hello,world!”是128kb。具有更多代码行的源文件增加了可执行文件的大小,正如我所期望的那样,但所有文件的起始时间至少为128kb,就好像这是某种最小大小。

我知道.exe实际上没有这样的最小尺寸; .kkrieger是一个完整的第一人称射击游戏,具有三维图形和声音,所有这些都适合一个96kb的可执行文件。

试图深入了解这一点,我在Notepad ++中打开了hello_world.exe。也许我的编译器添加了一个128kb的冗长标题,我想。

不幸的是,我不太了解可执行文件能够理解它,虽然我确实找到了像“地址%p没有图像部分VirtualQuery失败的地址%p的%d字节”之类的字符串.exe中通常的乱码。

当然,这不是一个严重的问题,但我想知道它为什么会发生。

为什么最低128kb的发生?它与我的64位操作系统有关,还是与编译器的怪癖有关?

1 个答案:

答案 0 :(得分:2)

简短回答:这取决于。

答案很长:这取决于您拥有的操作系​​统以及它如何处理可执行文件。

大多数(如果不是全部)编程语言编译器都没有将其分解为绝对的原始x86 / ARM /其他架构的机器代码。相反,在将源代码打包到.o(对象)文件之后,他们会带来.o及其库和"链接"它们一起形成一个标准的可执行格式。这些"可执行格式"本质上是系统特定的文件格式,包含低级,非常接近机器代码的指令,操作系统以这样的方式解释它可以以机器代码指令的形式将这些低级指令中继到CPU

例如,我将讨论Linux设备最常用的两种可执行格式:ELF和ELF64(我会让你弄清楚自己的名字差异)。 ELF代表可执行文件和可链接格式。在每个ELF编译的程序中,文件以一个4字节"幻数#34开始,它只是一个十六进制的0x7F,后跟字符串" ELF"用ASCII。下一个字节设置为1或2,表示该程序分别用于32位或64位体系结构。然后,另一个字节表示程序的endianness.之后,还有几个字节可以告诉架构是什么,依此类推,直到总共达到64个字节为止64位标头的字节数。

但是,64字节甚至不接近你所说的128K。这是因为(除了windows .exe格式通常要复杂得多),这里有C ++标准库。例如,让我们看一下C ++ iostream库的常见用法:

#include <iostream>
int main()
{
    std::cout<<"Hello, World!"<<std::endl;
    return 0;
}

这个程序可能会在Windows系统上编译成一个非常大的可执行文件,因为当你向程序添加iostream时,它会将整个C ++标准库添加到其中,从而极大地增加了可执行文件的大小。

那么,我们如何纠正这个问题呢?简单: 使用C ++的C标准库实现!

#include <cstdio>
int main()
{
    printf("Hello, World!\n");
    return 0;
}

简单地使用原始的C标准库可以将您的大小从几百KB减少到最多几个。发生这种情况的原因仅仅是因为GCC / G ++非常喜欢将程序与整个标准C ++库链接起来,原因有些奇怪。

但是,有时您绝对需要才能使用特定于C ++的库。在这种情况下,许多链接器都有某种命令行选项,基本上告诉链接器&#34;嘿,我只使用STDCPP库中的2个函数,你不需要整件事&#34;。在Linux链接器ld上,这是命令行选项-nodefaultlibs。不过,我并不完全确定它在Windows上是什么。当然,这可以很快打破TON的调用,例如在编写大量标准C ++调用的程序中。

所以,最后,我更担心的是简单地重新编写你的程序来使用常规的C函数而不是新的C ++函数,就像它们一样令人惊叹。那就是你担心尺寸。