6

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

MinGW g++ 下,我遇到了 .exe 大小的问题。(在使用可执行打包程序之前,我必须将其降低到 <100 kb。)。

我看过这个: 如何减少 MinGW g++ 编译器生成的可执行文件的大小? 但是我已经在使用 MinGW/g++ 4.8.1 和 -s -Os ...见下文(以及 4.8.1: unrecognized option '-shared-libstdc++'cannot find -lstdc++_s)。

这个小小的 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:是否可以让-shared-libstdc++ 或-lstdc++_s 在MinGW/g++ 4.8.1 中工作?

可选2:当我尝试-nostdlib替换mainWinMain

    #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

4 回答 4

6

这些额外的字节被标准库调用“拉入” - 高级字节倾向于将所有内容放在它们之下,内存分配,它们使用的异常等等。最简单的开始是尽量减少你使用的东西。基于 putchar() 的 hello world 可能会给您一个很好的比较点。我将专注于静态链接程序,因为这就是我所知道的,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 标志。

如果这还不够远,您可以在 ld 的 linux 版本上与标志 -Map=filename.map 链接以生成“地图”文件。输出文件的第一部分列出了被拉入的每个部分,以及需要它的部分。*

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

于 2013-08-27T09:11:48.580 回答
2

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

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

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

于 2013-08-27T07:24:30.120 回答
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

于 2013-08-27T08:24:39.857 回答
1

这是在黑暗中拍摄,但在链接时尝试 -fwhole-program 选项。编译和链接时 -flto 也可能会有所帮助

于 2013-08-26T17:16:55.230 回答