2015-09-13 45 views
-2

为什么可执行文件的文件大小比源文件大?我做了下面的例子(我能想到的最简单的例子),它的可执行文件与源代码相比仍然非常巨大,即使(我认为)它没有使用任何库。为什么可执行文件的文件大小比不带include的.cpp源文件大?

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上使用g ++编译器在cygwin上使用Intel处理器。

+1

_Not知道,如果是相关的,但我用G ++编译器在带有Intel处理器的Windows 8上的cygwin上._ < - 所有这些都与_absolutely_相关。 –

+1

您可以运行'objdump -s -d Simplest.exe'来查看最终可执行文件的内容。但我不确定该工具是否适用于您的平台。 – 5gon12eder

+0

@ 5gon12eder谢谢,我试过了,能够看到很多其他东西都包含在可执行文件中。 – circularsoggy

回答

3

可执行文件与许多库链接。所以,当编译器完成链接时,文件大小会增加。 libclibc++总是与您在构建C或C++程序时进行链接。

您可以阅读articlegcc的链接过程。

ld's manpage

LD结合了一些目标和归档文件,重定位数据,并链接符号引用。通常编译程序的最后一步是运行ld

总而言之,连接器可能会将很多东西放入可执行文件中。难怪为什么它的大小可能大于源文件的大小。


注:上面的链接是关于在Unix,而不是Windows的连接,但Cygwin的尝试以某种方式模拟Linux/Unix系统的行为,所以他们仍然具有现实意义。

+0

你应该解释什么库链接,当没有明确要求。 –

+0

@BenVoigt,完成 – ForceBru

+0

感谢您确切地知道哪些库链接 – circularsoggy

2

ForceBru已经解释了高层发生了什么,但似乎你已经理解链接库可能会增加可执行文件的大小,但(错误地)认为你的程序不使用库。

其实,因为你通过运行gcc链接你的程序,当ld被调用时,gcc传递了一些额外的选项。为了控制这一点,了解gcc Link Options

特别令人感兴趣的是-nostdlib-nodefaultlibs选项,说明如下:

-nodefaultlibs

不要使用链接时的标准系统库。只有指定的库被传递给链接器,并且忽略指定系统库链接的选项,如-static-libgcc-shared-libgcc。标准启动文件正常使用,除非使用-nostartfiles

编译器可能会生成对memcmp,memset,memcpymemmove的调用。这些条目通常由libc中的条目解决。当指定此选项时,应通过其他一些机制提供这些入口点。

-nostdlib

不要使用标准系统启动文件或链接时库。没有启动文件,只有指定的库传递给链接器,并且忽略指定系统库链接的选项,如-static-libgcc-shared-libgcc

编译器可能会生成对memcmp,memset,memcpymemmove的调用。这些条目通常由libc中的条目解决。当指定此选项时,应通过其他一些机制提供这些入口点。

一个由-nostdlib绕过了标准库和-nodefaultlibslibgcc.a,内部的子程序库,GCC用来克服特定的机器,或对某些语言的特殊需要的缺点。 (有关更多关于libgcc.a的讨论,请参见与GCC输出的接口。)在大多数情况下,即使您想避开其他标准库,也需要libgcc.a。换句话说,当您指定-nostdlib-nodefaultlibs时,通常也应指定-lgcc。这确保您没有未解析的对内部GCC库子例程的引用。 (这样的内部的子程序的一个例子是__main,用于确保C++构造函数的调用;参见collect2

因为你还没有使用这些选项,代码实际上正在与多个库链接。

了解一些这些图书馆提供的行为,否则即使你的小程序将失败,你可能会阅读博客系列Hello from a libc-free world!Part 2

+0

感谢您的答案和链接!你完全正确,我误解我的程序确实使用了库。 – circularsoggy

相关问题