编译的 C++ 可执行文件很大吗?
Posted
技术标签:
【中文标题】编译的 C++ 可执行文件很大吗?【英文标题】:Compiled C++ executables HUGE? 【发布时间】:2010-11-14 18:21:45 【问题描述】:在用 C 编程一段时间后,我决定最终开始学习 C++。这有点困扰我,因为 C 语言中的标准“hello world”通常约为 16KB,包括编译器在那里抛出的所有杂物。 (使用标准输出)
但是,当我创建一个执行 hello world 的 C++ 可执行文件时,该文件约为 470KB!我继续使用 cstdio 而不是 iostream,认为它会有所作为。
我的问题是: 当我包含 iostream 时,为什么我的可执行文件的大小会爆炸?
编辑:我正在使用 G++(使用 Dev-CPP IDE,但我可以弄清楚如何添加 CL 参数)
【问题讨论】:
我想指出 Dev-C++ 带有一个 非常 旧版本的 GCC。考虑迁移到 wxDev-C++ 或 Code::Blocks,这两者都更新了很多。 【参考方案1】:总之,符号。
C++ 标准库为您的程序引入了很多符号,因为大多数库主要存在于头文件中。
在发布模式下重新编译您的程序并且不使用调试符号,您可以很容易地预期程序会明显变小。 (如果去掉符号会更小。)
作为对这一事实的快速演示,请注意:
$ cat hello.c
#include <stdio.h>
int main()
printf("%s\n", "Hello, world!");
return 0;
$ cat hello.cpp
#include <iostream>
int main()
std::cout << "Hello, world!\n";
return 0;
$ gcc hello.c -o hello-c
$ g++ hello.cpp -o hello-cpp
$ gcc hello.c -ggdb -o hello-c-debug
$ g++ hello.cpp -ggdb -o hello-cpp-debug
$ gcc hello.c -s -o hello-c-stripped
$ g++ hello.cpp -s -o hello-cpp-stripped
$ gcc hello.c -s -O3 -o hello-c-stripped-opt
$ g++ hello.cpp -s -O3 -o hello-cpp-stripped-opt
$ ls -gG hello*
-rwxr-xr-x 1 6483 Nov 14 15:39 hello-c*
-rw-r--r-- 1 79 Nov 14 15:38 hello.c
-rwxr-xr-x 1 7859 Nov 14 15:40 hello-c-debug*
-rwxr-xr-x 1 7690 Nov 14 15:39 hello-cpp*
-rw-r--r-- 1 79 Nov 14 15:38 hello.cpp
-rwxr-xr-x 1 19730 Nov 14 15:40 hello-cpp-debug*
-rwxr-xr-x 1 5000 Nov 14 15:45 hello-cpp-stripped*
-rwxr-xr-x 1 4960 Nov 14 15:41 hello-cpp-stripped-opt*
-rwxr-xr-x 1 4216 Nov 14 15:45 hello-c-stripped*
-rwxr-xr-x 1 4224 Nov 14 15:41 hello-c-stripped-opt*
我无法解释为什么使用 G++ 构建的 Windows 程序会产生如此大的可执行文件,但在任何其他平台上,符号是大文件大小的主要驱动因素。我目前无法访问 Windows 系统,因此无法测试。
【讨论】:
您好,感谢您抽出宝贵的时间来做结果。我在 Windows 中使用“-s -O3”标志执行此操作,文件大小从 475kb 减少到 263kb。它有帮助,但我还能做些什么吗? @Saustin:使用更新的编译器。您使用的是非常旧的。它可能带有一些不会被更新到新版本的杂物。 Dev-C++ 无论如何都没有维护,所以当有这么多其他更好的选择时,没有理由继续使用它。我的意思是,最近一次发布是在 2005 年! 这是真的;有没有你会碰巧推荐的编译器? (PS:抱歉验证了很久!) @Saustin:Code::Blocks 打包的 MinGW 版本是最新的。与wxDev-C++(与您使用的不同)打包的那个是最新的。您也可以使用Visual Studio 2010 Express,它也是最新的。【参考方案2】:因为您已经使用 iostreams 拖入了大部分标准库。 虽然这是一次性的事情,所以随着您的程序变得越来越大,它的开销似乎越来越少。
但是,您可能希望使用标准库的共享库版本进行编译,并且大多数编译器/操作系统都允许您这样做,因此您不必在可执行文件中包含所有标准库。您使用的是哪个编译器,我们可能会就如何操作提供建议。
在带有 VC 命令行的窗口上,例如使用 /MD 命令行选项。
【讨论】:
【参考方案3】:我猜想通过包含 <iostream>
,您间接包含了 STL 的许多部分,例如 <string>
,其中又包含 <vector>
等。
【讨论】:
用 C 术语来表达这个答案,就是使用 putc 和 printf 的区别。 printf 代码有很多功能,可以(相对地)将您的 C 可执行文件与简单的 putc 函数相结合。对于 Saustin 的情况,这更像是您使用的编译器(和选项)的产物,而不是其他任何东西。使用 MS VC++,根据我使用的编译器标志,我可以得到从 ~8K 到 ~110K 的任何位置。使用 MinGW,我得到大约 24-25K(同样,取决于标志)。
以防万一您想知道,我猜想我使用 VC++ 获得的更大范围主要是因为更好地了解其标志。 MinGW 可能 只覆盖较小的范围,即使我更了解它,但由于我对其标志的了解有限,我接受了它默认执行的大部分操作;我知道如何打开和关闭优化,但必须非常仔细地看待事情才能做更多的事情。
【讨论】:
【参考方案5】:MinGW (g++) 编译非常大的文件。 例如,带有 iostreams 的相同“hello world”程序由 VC++(使用静态链接 CRT)编译为 ~100KB,由 g++ 编译为 ~470KB。
【讨论】:
最新的 Visual Studio 和带有 GCC 7.2.0 的 MinGW w-64 仍然如此(使用 CMake 用于发布版本的标准编译器标志)。【参考方案6】:这是fake C++ interview 的一个方面,实际上是真的:)
您知道,当我们在 AT&T 拥有第一个 C++ 编译器时,我编译了“Hello World”,并且无法相信可执行文件的大小。 2.1MB
什么?好吧,从那时起,编译器已经走了很长一段路。
他们有吗?在最新版本的 g++ 上尝试一下 - 半兆字节不会有太大变化。
【讨论】:
不是很有帮助,但一些幽默会有所帮助。以上是关于编译的 C++ 可执行文件很大吗?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Visual C++ 编译器将未使用的类编译成可执行文件?
双击编译的 C++ Unix 可执行文件未打开现有文件以从中读取信息