6

私は通常、サイズコーディングのデモ作成コンテスト (64kb) のために C で書いていますが、C++ に移行することを検討しています。

MinGW g++では、.exe のサイズに問題があります。(executable-packers を使用する前に、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;

193kbになります

そして、私が追加すると:

#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と置き換えようと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

4 に答える 4

6

これらの余分なバイトは、標準ライブラリ呼び出しによって「引き込まれ」ます。高レベルのものは、メモリ割り当て、使用する例外など、すべてをそれらの下に持ち込む傾向があります。最も簡単な方法は、使用するものを最小限に抑えることです。putchar() に基づいて hello world を作成すると、適切な比較ポイントが得られる場合があります。それは私が知っていることなので、静的にリンクされたプログラムに焦点を当てます。とにかく、ruvenvbの答えは共有ライブラリをうまくカバーしているようです。

new、delete、pure virtual functions などの機能は、ライブラリのビットとその下にある多くの依存関係も取り込みます。それらを置き換える方法の簡単な概要は、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 を使用してリンクし、「マップ」ファイルを生成できます。出力されるファイルの最初のセクションには、プルされた各セクションと、それを必要とするセクションがリストされます。*

*マップファイルは、関数セクションが標準ライブラリに対して何もしないことも明らかにします。これは、それとは別に、そのフラグなしで既にコンパイルされているためです。

于 2013-08-27T09:11:48.580 に答える
2

MinGW GCC でコンパイルされた実行可能ファイルが機能するために必要な余分なコードを取り除く方法はありません。CRT へのアプローチが異なる MinGW-w64 ツールチェーンを試すこともできますが、「Hello world」のサイズに関しては、通常の MinGW よりも劣る可能性があります。

OS に組み込まれている独自の CRT コードに依存しているため、バイナリ サイズが重要な場合は MSVC を使用することを強くお勧めします。これは、ある意味で「不正行為」と慎重に呼ぶかもしれません:-)。

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 に答える