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

时间:2013-08-24 01:36:36

标签: c++ windows mingw executable

我通常用C语言编写大小编码演示竞赛(64kb),但考虑转向C ++。

MinGW g ++下,我对.exe-size有些麻烦。 (在使用可执行程序包装程序之前,我必须将其降低到<100 kb。)。

我看过这个:  How to reduce the size of executable produced by MinGW g++ compiler? 但是我已经使用MinGW / g ++ 4.8.1和-s -Os ...见下文(也适用于4.8.1:unrecognized option '-shared-libstdc++'cannot find -lstdc++_s)。< / p>

这个小小的helloworld只有 10 kb(没关系):

#include "windows.h"
int main() {
    MessageBoxA(0, "test", "test", 0);
    return 0;
}

然而,当我添加:

#include <string>
...
std::string asdf;

它变为 193 kb

当我添加:

#include <iostream>

然后它变为 756 kb。

我正在使用这些标志:

-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 ++或-lstdc ++ _?

可选2:当我尝试-nostdlib并将main替换为WinMain时:

    #include "windows.h"
    int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
        LPSTR lpCmdLine, int nCmdShow) {
        MessageBoxA(0, "test", "test", 0);
        return 0;
    }

我没有编译器警告但是运行时崩溃,它在编译为C时工作正常。 (可选,因为我不希望你/我花时间调试crt-startup,编译器 - 链接器标志来修剪库会更有帮助)

4 个答案:

答案 0 :(得分:4)

这些额外的字节被标准库调用“拉入” - 高级别的字节往往会带来它们下面的所有内容,内存分配,它们使用的异常等等。最简单的方法是尽量减少使用的内容。在putchar()上建立一个hello世界可能会给你一个很好的比较点。我将专注于静态链接的程序,因为我知道,rubenvb的答案似乎也很好地涵盖了共享库。

新功能,删除功能,纯虚函数功能等功能也可以提取库中的位以及下面的许多依赖项。这里有一个关于如何替换它们的快速概述:http://ptspts.blogspot.com.au/2010/12/how-to-write-c-program-without-libstdc.html - 如果你真的很极端,你可以找到一个以相同方式处理的malloc版本。

最近使用C ++ 11,如果你这样做,你会遇到__cxa_guard_acquire和__cxa_guard_release:

int foo() {
    static int bar = 1; //thread safe in C++11, requires inbuilt functions
}

为此,如果编译器支持,请使用-fno-threadsafe-statics标志。

如果这对你的影响不够大,你可以在linux版本的ld上链接标志-Map = filename.map来生成“map”文件。输出文件的第一部分列出了所引入的每个部分以及需要它的部分。*

*地图文件还会显示函数部分对标准库没有任何作用,因为它已经在没有该标志的情况下编译,除此之外

答案 1 :(得分:2)

你无法摆脱MinGW GCC编译的可执行文件需要运行的额外代码。您可以尝试使用MinGW-w64工具链,它以不同的方式接近CRT,但就“Hello world”大小而言,它可能比普通MinGW更差。

如果二进制大小非常重要,我强烈建议使用MSVC,因为它依赖于自己内置于操作系统的CRT代码。我可以用某种方式小心地称之为“作弊”: - )。

关于DLL libstdc ++,当然有可能,你只需要一个像样的工具链;-)。见here。请注意,这也是“作弊”,因为我怀疑比赛会忽略运行时库的大小。这就是代码化比赛是愚蠢的原因。总是有一个你忽略的运行时层。直到你击中裸机内核或组装,这不是所述比赛的重点。

答案 2 :(得分:1)

我尝试在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大小 34 kb, 在调试模式下,exe大小为 92 kb

答案 3 :(得分:0)

这是黑暗中的一个镜头,但在链接时尝试-fwhole-program选项。同时-flto编译和链接时可能会有所帮助