使用MinGW的C++可执行文件大小

C++ executable size using MinGW

本文关键字:可执行 文件大小 C++ MinGW 使用      更新时间:2023-10-16

我通常用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