使用MinGW的C++可执行文件大小
C++ executable size using MinGW
我通常用C语言为sizecoding演示制作竞争(64kb)编写代码,但考虑改用C++。
在MinGWg++下,我的.exe大小有一些问题。(在使用可执行打包程序之前,我必须将其降到<100kb。)。
我看了一下:如何减少MinGW g++编译器生成的可执行文件的大小?然而,我已经使用MinGW/g++4.8.1和-s-Os。。。参见下文(以及4.8.1:unrecognized option '-shared-libstdc++'
和cannot find -lstdc++_s
)。
这个小helloworld只有10kb(可以):
#include "windows.h"
int main() {
MessageBoxA(0, "test", "test", 0);
return 0;
}
然而,当我添加:
#include <string>
...
std::string asdf;
它变成193kb
当我加上:
#include <iostream>
则变为756kb。
我正在使用这些标志:
-std=c++11
-Wall
-s (or -Wl,-s)
-Os
-DNDEBUG
-fno-exceptions
-fno-rtti
(note: removed those with no effect)
必须有某种方法来只链接我使用的内容。我错过了什么?
可选1:是否可以在MinGW/g++4.8.1中使用-shared libstdc++或-lsdc++_s?
可选2:当我尝试-nostdlib
并用WinMain
:替换main
时
#include "windows.h"
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
MessageBoxA(0, "test", "test", 0);
return 0;
}
我没有收到编译器警告,但出现了运行时崩溃,不过当编译为C时,它运行良好。(可选,因为我不想让你/我花时间调试crt启动,一个用于修剪库的编译器链接器标志会更有帮助)
这些额外的字节是由标准库调用"拉入"的-高级调用往往会带来低于它们的所有内容、内存分配、它们使用的异常等等。最简单的方法是尽量减少使用的内容。基于putchar.()的hello世界可能会给你一个很好的比较点。我将专注于静态链接的程序,因为这就是我所知道的,ruenvb的答案似乎涵盖了共享库。
诸如new、delete、纯虚拟函数等功能也会引入库中的一些部分和下面的许多依赖项。关于如何更换这些部件的快速概述如下:http://ptspts.blogspot.com.au/2010/12/how-to-write-c-program-without-libstdc.html-如果你真的变得极端,你可能会发现malloc的一个版本也以同样的方式处理。
最近使用C++11时,如果您这样做,您将遇到__cxa_ard_acquise和__cxa\uaguard_release:
int foo() {
static int bar = 1; //thread safe in C++11, requires inbuilt functions
}
为此,如果编译器支持,请使用-fno线程安全静态标志。
如果这还不够,您可以在ld的linux版本上使用标记-Map=filename.Map链接以生成一个"Map"文件。输出文件的第一部分列出了被拉入的每个部分,以及需要它的部分。*
*映射文件还显示,函数部分对标准库没有任何作用,因为它已经在没有该标志的情况下编译了,除了
无法摆脱MinGW GCC编译的可执行文件运行所需的额外代码。你可能会尝试一个MinGW-w64工具链,它以不同的方式处理CRT,但就"你好世界"的大小而言,它可能比普通的MinGW更糟糕。
如果二进制大小如此重要,我强烈建议使用MSVC,因为它依赖于操作系统中内置的CRT代码。在某种程度上,我可以谨慎地称之为"作弊":-)。
关于DLL libstdc++,当然有可能,您只需要一个像样的工具链;-)。请参见此处。请注意,这也是"作弊",因为我怀疑比赛会忽略运行库的大小。这就是为什么代码大小竞赛是愚蠢的。运行时中总会有另一层被您忽略。直到你碰到裸露的金属内核或组件,这不是比赛的重点。
这是一个未知数,但在链接时请尝试-fwhole程序选项。此外,编译和链接时-flto可能有助于
我试图在QT 5.1.0 MinGW 4.8 32位下运行您的代码
#include "windows.h"
#include <string>
#include <iostream>
int main() {
MessageBoxA(0, "test", "test", 0);
std::string asdf;
return 0;
}
在发布模式下,exe的大小为34kb,在调试模式下,exe大小为92kb
- 如何将不同的可执行文件合并到一个窗口框架中进行编码?像浏览器一样
- 如何使 windows 命令提示符在C++可执行文件上显示返回值?
- CMake:如何将库 A 链接到库 B,然后将可执行文件链接到库 A
- 如何使字符串出现在编译的二进制可执行文件的开头?
- 程序在使用 system() 启动另一个可执行文件时停止
- 相同的源代码,不同的可执行文件大小?
- 在 Linux 上没有 /proc/self/exe 的 C/C++ 运行时可执行文件的大小?
- 仅针对特定可执行文件增加堆栈大小
- 为什么?在改变构建结构后,可执行文件的大小显著减少
- #include 多个.cpp中的标准文件,与将其 #include 在预编译标头中会影响可执行文件的大小?
- 链接后的最小可执行文件大小
- 为什么使用VS 2012构建的MFC对话框的可执行文件大小几乎是使用VS 2005构建的对话框的3倍
- 使用MinGW的C++可执行文件大小
- C++数据类型及其对可执行文件大小的影响
- Borland c++ Builder 6调整输出可执行文件大小,以适应屏幕
- 减少与opencv静态链接的可执行文件的大小
- 使用枚举如何增加可执行文件的大小
- 链接库两次,可执行文件大小
- 重载函数和可执行文件/库的大小
- 为什么在 Visual C++ 9 中更喜欢 /Ob1 而不是 /Ob2,而可执行文件大小没有严格的限制?