为什么可执行文件的文件大小大于源文件?我做了下面的例子(我能想到的最简单的例子),而且与源相比,可执行文件仍然是如此巨大,尽管(我认为)它没有使用任何库。
Simplest.cpp:33个字节
Simplest.s:386字节
Simplest.exe:60076字节
Simplest.cpp:
int main(void)
{
return 0;
}
Simplest.s:
.file "Simplest.cpp"
.def ___main; .scl 2; .type 32; .endef
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
call ___main
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
.ident "GCC: (GNU) 4.8.3"
不确定它是否相关,但我在Windows 8上使用英特尔处理器在cygwin上使用g ++编译器。
答案 0 :(得分:3)
可执行文件与许多库链接。因此,当您的编译器完成链接时,文件大小会增加。当您构建C或C ++程序时,始终会链接libc
或libc++
。
您可以阅读此article关于 gcc 的关联过程。
ld 组合了许多对象和档案文件,重新定位了他们的数据并绑定了符号引用。通常,编译程序的最后一步是运行 ld 。
总而言之,链接器可能会将大量内容放入可执行文件中。难怪为什么它的大小可能大于源文件的大小。
注意:上面的链接是关于Unix上的链接,而不是Windows,但Cygwin尝试以某种方式模拟Linux / Unix系统的行为,因此它们仍然相关。
答案 1 :(得分:2)
ForceBru已经解释了高级别的内容,但似乎您已经明白链接库可能会增加可执行文件的大小,但(错误地)认为您的程序不使用库。
实际上,因为您通过运行gcc
链接了您的程序,所以在调用ld
时,gcc
传递了一些额外的选项。要控制此操作,请阅读gcc
Link Options
特别感兴趣的是-nostdlib
和-nodefaultlibs
选项,描述如下:
-nodefaultlibs
链接时不要使用标准系统库。只有您指定的库才会传递给链接器,并且会忽略指定系统库链接的选项,例如
-static-libgcc
或-shared-libgcc
。除非使用-nostartfiles
,否则标准启动文件将正常使用。编译器可能会生成对
memcmp
,memset
,memcpy
和memmove
的调用。这些条目通常由libc
中的条目解决。当指定此选项时,应通过其他机制提供这些入口点。
-nostdlib
链接时请勿使用标准系统启动文件或库。没有启动文件,只有您指定的库被传递给链接器,并且忽略指定系统库链接的选项,例如
-static-libgcc
或-shared-libgcc
。编译器可能会生成对
memcmp
,memset
,memcpy
和memmove
的调用。这些条目通常由libc
中的条目解决。当指定此选项时,应通过其他机制提供这些入口点。
-nostdlib
和-nodefaultlibs
绕过的标准库之一是libgcc.a
,这是一个内部子程序库,GCC使用它来克服特定机器的缺点或某些语言的特殊需求。 (有关libgcc.a
的更多讨论,请参阅与GCC输出的接口。)在大多数情况下,即使您想要避免使用其他标准库,也需要libgcc.a
。换句话说,当您指定-nostdlib
或-nodefaultlibs
时,通常也应指定-lgcc
。这可确保您没有对内部GCC库子例程的未解析引用。 (此类内部子例程的示例是__main
,用于确保调用C ++构造函数;请参阅collect2
。)
由于您还没有使用这些选项,因此您的代码 实际上与多个库相关联。
要了解这些库提供的某些行为,即使您的小程序失败,您也可以阅读博客系列Hello from a libc-free world!(Part 2)