简体   繁体   English

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

[英]C++ executable size using MinGW

I am normally writing in C for sizecoding demo-making competition (64kb) but considering moving to C++. 我通常用C编写大小编码演示竞赛(64kb),但考虑转向C ++。

Under MinGW g++ i have some trouble with the .exe-size. MinGW g ++下,我对.exe-size有些麻烦。 (Before using executable-packers, i have to get it down to <100 kb.). (在使用可执行程序包装程序之前,我必须将其降低到<100 kb。)。

I have looked at this: How to reduce the size of executable produced by MinGW g++ compiler? 我看过这个: 如何减少MinGW g ++编译器生成的可执行文件的大小? however i am already using MinGW/g++ 4.8.1 and -s -Os ... see below (and for 4.8.1 too: unrecognized option '-shared-libstdc++' and cannot find -lstdc++_s ). 但是我已经在使用MinGW / g ++ 4.8.1和-s -Os ...见下文(对于4.8.1也是如此: unrecognized option '-shared-libstdc++'并且cannot find -lstdc++_s )。

This little helloworld has only 10 kb (which is ok): 这个小小的helloworld只有10 kb(可以):

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

However when i add: 但是,当我添加:

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

it becomes 193 kb 它变成193 kb

And when i add: 当我添加:

#include <iostream>

then it becomes 756 kb. 然后它变成756 kb。

I am using these flags: 我正在使用这些标志:

-std=c++11
-Wall
-s       (or -Wl,-s)
-Os
-DNDEBUG
-fno-exceptions
-fno-rtti
(note: removed those with no effect)

There has to be some way to only link what i use. 必须有一些方法只链接我使用的东西。 What am i missing? 我错过了什么?

Optional 1: Is it possible to get -shared-libstdc++ or -lstdc++_s working in MinGW/g++ 4.8.1? 可选1:是否可以在MinGW / g ++ 4.8.1中使用-shared-libstdc ++或-lstdc ++ _ s?

Optional 2: When I try -nostdlib and replace main with WinMain : 可选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;
    }

I get no compiler warnings but a runtime crash, it works fine when compiling as C though. 我没有编译器警告,但运行时崩溃,它编译为C时工作正常。 (optional because I don't want you/me to spend time debugging crt-startup, a compiler-linker-flag to trim libraries would be more helpful) (可选,因为我不希望你/我花时间调试crt-startup,编译器 - 链接器标志来修剪库会更有帮助)

Those extra bytes are "pulled in" by standard library calls - the high level ones tend to bring everything below them along, memory allocation, the exceptions they use and so on. 这些额外的字节被标准库调用“拉入” - 高级别的字节往往会带来它们下面的所有内容,内存分配,它们使用的异常等等。 The easiest thing to start with is to minimize what you use. 最简单的方法是尽量减少使用的内容。 Basing a hello world on putchar() might give you a good point of comparison. 在putchar()上建立一个hello世界可能会给你一个很好的比较点。 I'll focus on statically linked programs as that's what I know, rubenvb's answer appears to cover shared libraries well anyway. 我将专注于静态链接的程序,因为我知道,rubenvb的答案似乎无论如何都能很好地覆盖共享库。

Features like new, delete, pure virtual functions etc. pull in bits of the library too and many dependencies underneath. 新的,删除,纯虚函数等功能也可以提取库中的位以及下面的许多依赖项。 A quick overview on how to replace those is here: http://ptspts.blogspot.com.au/2010/12/how-to-write-c-program-without-libstdc.html - if you get really extreme, you could find a version of malloc treated in the same way. 关于如何替换它们的快速概述在这里: http//ptspts.blogspot.com.au/2010/12/how-to-write-c-program-without-libstdc.html - 如果你真的很极端,你可以找到以相同方式处理的malloc版本。

More recently with C++11 you'll run into __cxa_guard_acquire and __cxa_guard_release if you do this: 最近使用C ++ 11,如果你这样做,你将遇到__cxa_guard_acquire和__cxa_guard_release:

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

For that, use the -fno-threadsafe-statics flag if your compiler supports it. 为此,如果编译器支持,请使用-fno-threadsafe-statics标志。

If that doesn't quite get you far enough you can link with the flag -Map=filename.map on linux versions of ld to generate a "map" file. 如果这不能让你足够远,你可以链接linux版本的ld上的标志-Map = filename.map来生成一个“map”文件。 The first section of the file that outputs lists each section that was pulled in, along with the one that required it.* 输出文件的第一部分列出了每个被拉入的部分以及需要它的部分。*

*The map file would also reveal that function-sections does nothing to the standard library as it's already been compiled without that flag, apart from that *地图文件还会显示函数部分对标准库没有任何作用,因为它已经在没有该标志的情况下编译,除此之外

There is no way you can get rid of the extra code MinGW GCC compiled executables need to function. 你无法摆脱MinGW GCC编译的可执行文件需要运行的额外代码。 You might try a MinGW-w64 toolchain, which approaches the CRT differently, but it might be worse than plain MinGW in terms of "Hello world" size. 您可以尝试使用MinGW-w64工具链,它以不同的方式接近CRT,但就“Hello world”大小而言,它可能比普通MinGW更差。

I strongly suggest using MSVC if binary size is that important, as it relies on its own CRT code built in to the OS. 如果二进制大小非常重要,我强烈建议使用MSVC,因为它依赖于自己内置于操作系统的CRT代码。 Which I may carefully call "cheating" in some way :-). 我可以用某种方式小心地称之为“作弊”:-)。

About the DLL libstdc++, of course it's possible, you just need a decent toolchain ;-). 关于DLL libstdc ++,当然有可能,你只需要一个像样的工具链;-)。 See here . 看到这里 Note that this is also "cheating", because I doubt the contest will ignore the size of the runtime libraries. 请注意,这也是“作弊”,因为我怀疑比赛会忽略运行时库的大小。 This is why codesize contests are stupid. 这就是代码化比赛是愚蠢的原因。 There is always another layer of the runtime you're ignoring. 总是有一个你忽略的运行时层。 Until you hit bare metal kernel or assembly, which is not the point of said contest. 直到你击中裸机内核或组装,这不是所谓的比赛的重点。

I tried to run your code under QT 5.1.0 MinGW 4.8 32 bit 我试图在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;
}

In release mode exe size is 34 kb, in debug mode exe size is 92 kb 在发布模式下,exe大小为34 kb,在调试模式下,exe大小为92 kb

It's a shot in the dark, but try -fwhole-program option when linking. 它是黑暗中的一个镜头,但在链接时尝试-fwhole-program选项。 Also -flto when compiling and linking may be helpful 同时-flto编译和链接可能会有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM