为什么可执行文件的文件大小比没有包含的 .cpp 源文件大?
Why is the file size of the executable file larger than the .cpp source file with no includes?
为什么可执行文件的文件大小比源文件大?我做了下面的例子(我能想到的最简单的例子),它的可执行文件与源代码相比仍然很大,即使(我认为)它没有使用任何库。
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 [=11=], %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
.ident "GCC: (GNU) 4.8.3"
不确定它是否相关,但我在 Windows 8 的 cygwin 上使用英特尔处理器的 g++ 编译器。
可执行文件与许多库链接。因此,当您的编译器完成链接时,文件大小会增加。当您构建 C 或 C++ 程序时,libc
或 libc++
总是链接在一起。
您可以阅读这篇关于 gcc 链接过程的 article。
ld combines a number of object and archive files, relocates their data and ties up symbol references. Usually the last step in compiling a program is to run ld.
总而言之,链接器可能会将很多东西放入可执行文件中。难怪为什么它的大小可以大于源文件的大小。
注意:上面的链接是关于在 Unix 上的链接,而不是 Windows,但是 Cygwin 试图以某种方式模拟 Linux/Unix 系统的行为,所以它们仍然相关。
ForceBru 已经在较高层次上解释了发生了什么,但您似乎已经了解链接库会增加可执行文件的大小,但(错误地)认为您的程序不使用任何库。
实际上,因为您通过 运行 gcc
链接了您的程序,所以当 ld
被调用时,gcc
传递了一些额外的选项。要控制这一点,请阅读 gcc
Link Options
特别感兴趣的是 -nostdlib
和 -nodefaultlibs
选项,描述如下:
-nodefaultlibs
Do not use the standard system libraries when linking. Only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as -static-libgcc
or -shared-libgcc
, are ignored. The standard startup files are used normally, unless -nostartfiles
is used.
The compiler may generate calls to memcmp
, memset
, memcpy
and memmove
. These entries are usually resolved by entries in libc
. These entry points should be supplied through some other mechanism when this option is specified.
-nostdlib
Do not use the standard system startup files or libraries when linking. No startup files and only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as -static-libgcc
or -shared-libgcc
, are ignored.
The compiler may generate calls to memcmp
, memset
, memcpy
and memmove
. These entries are usually resolved by entries in libc
. These entry points should be supplied through some other mechanism when this option is specified.
One of the standard libraries bypassed by -nostdlib
and -nodefaultlibs
is libgcc.a
, a library of internal subroutines which GCC uses to overcome shortcomings of particular machines, or special needs for some languages. (See Interfacing to GCC Output, for more discussion of libgcc.a
.) In most cases, you need libgcc.a
even when you want to avoid other standard libraries. In other words, when you specify -nostdlib
or -nodefaultlibs
you should usually specify -lgcc
as well. This ensures that you have no unresolved references to internal GCC library subroutines. (An example of such an internal subroutine is __main
, used to ensure C++ constructors are called; see collect2
.)
因为您没有使用这些选项,您的代码实际上是与多个库链接。
要了解这些库提供的某些行为,如果没有这些行为,即使您的小程序也会失败,您可以阅读博客系列 Hello from a libc-free world! (Part 2)
为什么可执行文件的文件大小比源文件大?我做了下面的例子(我能想到的最简单的例子),它的可执行文件与源代码相比仍然很大,即使(我认为)它没有使用任何库。
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 [=11=], %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
.ident "GCC: (GNU) 4.8.3"
不确定它是否相关,但我在 Windows 8 的 cygwin 上使用英特尔处理器的 g++ 编译器。
可执行文件与许多库链接。因此,当您的编译器完成链接时,文件大小会增加。当您构建 C 或 C++ 程序时,libc
或 libc++
总是链接在一起。
您可以阅读这篇关于 gcc 链接过程的 article。
ld combines a number of object and archive files, relocates their data and ties up symbol references. Usually the last step in compiling a program is to run ld.
总而言之,链接器可能会将很多东西放入可执行文件中。难怪为什么它的大小可以大于源文件的大小。
注意:上面的链接是关于在 Unix 上的链接,而不是 Windows,但是 Cygwin 试图以某种方式模拟 Linux/Unix 系统的行为,所以它们仍然相关。
ForceBru 已经在较高层次上解释了发生了什么,但您似乎已经了解链接库会增加可执行文件的大小,但(错误地)认为您的程序不使用任何库。
实际上,因为您通过 运行 gcc
链接了您的程序,所以当 ld
被调用时,gcc
传递了一些额外的选项。要控制这一点,请阅读 gcc
Link Options
特别感兴趣的是 -nostdlib
和 -nodefaultlibs
选项,描述如下:
-nodefaultlibs
Do not use the standard system libraries when linking. Only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as
-static-libgcc
or-shared-libgcc
, are ignored. The standard startup files are used normally, unless-nostartfiles
is used.The compiler may generate calls to
memcmp
,memset
,memcpy
andmemmove
. These entries are usually resolved by entries inlibc
. These entry points should be supplied through some other mechanism when this option is specified.
-nostdlib
Do not use the standard system startup files or libraries when linking. No startup files and only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as
-static-libgcc
or-shared-libgcc
, are ignored.The compiler may generate calls to
memcmp
,memset
,memcpy
andmemmove
. These entries are usually resolved by entries inlibc
. These entry points should be supplied through some other mechanism when this option is specified.One of the standard libraries bypassed by
-nostdlib
and-nodefaultlibs
islibgcc.a
, a library of internal subroutines which GCC uses to overcome shortcomings of particular machines, or special needs for some languages. (See Interfacing to GCC Output, for more discussion oflibgcc.a
.) In most cases, you needlibgcc.a
even when you want to avoid other standard libraries. In other words, when you specify-nostdlib
or-nodefaultlibs
you should usually specify-lgcc
as well. This ensures that you have no unresolved references to internal GCC library subroutines. (An example of such an internal subroutine is__main
, used to ensure C++ constructors are called; seecollect2
.)
因为您没有使用这些选项,您的代码实际上是与多个库链接。
要了解这些库提供的某些行为,如果没有这些行为,即使您的小程序也会失败,您可以阅读博客系列 Hello from a libc-free world! (Part 2)