web-dev-qa-db-ja.com

GCC C ++の「HelloWorld」プログラム->。exeは、Windowsでコンパイルすると500kbの大きさになります。どうすればサイズを小さくできますか?

私は最近C++の学習を始めました-私はWindowsでMingWの nuwen's バージョンを使用しています。NetBeansをIDEとして使用しています(ただし、MSVC2008のMSDNAAバージョンもあります)あまり使用しません)。

この単純なプログラムをコンパイルするとき:

#include <iostream>
using namespace std;

int dog, cat, bird, fish;

void f(int pet) {
  cout << "pet id number: " << pet << endl;
}

int main() {
  int i, j, k;
  cout << "f(): " << (long)&f << endl;
  cout << "dog: " << (long)&dog << endl;
  cout << "cat: " << (long)&cat << endl;
  cout << "bird: " << (long)&bird << endl;
  cout << "fish: " << (long)&fish << endl;
  cout << "i: " << (long)&i << endl;
  cout << "j: " << (long)&j << endl;
  cout << "k: " << (long)&k << endl;
} ///:~

私の実行可能ファイルは約1MBの大きさでした。プロジェクト構成をDebugからReleaseに変更したとき、-O1-を使用しましたOSフラグ(途中でデバッグシンボルを削除)、バイナリサイズが1MBから544KBに減少しました。

私は「サイズフリーク」ではありませんが、疑問に思っています。exeのサイズをさらに小さくする方法はありますか? 544KBは、このような単純なアプリケーションには多すぎると思います)。

30
zeroDivisible

ザ・

#include <iostream>

少なくともg ++では、多くの標準ライブラリがリンクされます。実行可能ファイルのサイズが本当に心配な場合は、iostreamのすべての使用をprintfなどに置き換えてみてください。これにより、通常、利便性と型の安全性を犠牲にして、より小さく、より高速な実行可能ファイル(約6Kまで下げました)が提供されます。

22
anon

それがどれだけ使用されるかはわかりませんが、 誰かが単純なWindows .exeのサイズを縮小するためにかなりの作業を行っています

彼らは、いくつかの非常に極端な方法を使用して、最新バージョンのWindowsで133バイトで実行される単純な.exeを作成することができました。

10
Colin Pickard

-sを使用することもできますが、これはmingwにも組み込まれていると思います。 cygwinでg ++ 3.4.4を使用してコンパイルされた単純なhelloworldアプリケーションは、476872バイトの実行可能ファイルを生成し、-s(不要なデータを削除)で再度コンパイルすると、同じ実行可能ファイルが276480バイトに削減されました。

G ++ 4.3.2を使用するcygwin上の同じhelloworldアプリケーションは、16495バイトの実行可能ファイルを生成し、stripを使用してサイズを4608バイトに縮小しました。私が見る限り、おそらく最新バージョンのg ++​​を使用するのが最善でしょう。

MingWはgcc4.4.0をリリースしたばかりなので、実行可能サイズが重要な場合は、それを使用することを検討します。 -sが示すように、デバッグ情報の多くを取り除くのに役立つ可能性があります。これは、本番環境で使用する場合にのみ推奨されます。

9
Randai

Mingwにはこれらのライブラリの独自の実装があるため、静的にリンクされたC++標準ライブラリやその他のものを入手できます。

より複雑なプログラムを作成すると、それに応じてサイズが大きくなることはありませんので、それほど心配する必要はありません。

8
nos

基本的に、mingwの基本配布でその.exeサイズを減らすためにできることは実際には何もありません。 mingwとgcc/g ++は一般に未使用の関数を取り除くのが苦手なので、550kbはあなたがそれを得ることができるのとほぼ同じくらい小さいです。その約530kbはmsvcrt.aライブラリからのものです。

本当に入りたい場合は、-ffunction-sections -fdata-sectionsコンパイラオプションを使用してmsvcrt.aライブラリを再構築し、アプリをリンクするときに-Wl、-gc-sectionsリンカーオプションを使用できる場合があります。 、そしてこれはそこからそのようなものの多くを取り除くことができるはずです。ただし、C++を学習しているだけの場合は、そのライブラリの再構築が少し進んでいる可能性があります。

または、MSVCを使用することもできます。これは、未使用の関数を取り除くのに最適です。 MSVCでコンパイルされた同じビットのコードは、10kbのexeファイルを生成します。

4
Gerald

「nm」ユーティリティまたは.exeの内容を表示するその他のプログラムを使用すると、誰か可能性のあるクラスが大量に含まれていることがわかります。 )使用したいが、使用しないこと。

2
Mike Dunlavey

Cygwinとg ++を使用してテストを複製しました。コードを-O2で480kにコンパイルしました。ランニング ストリップ 実行可能ファイルでそれを280kに減らしました。

ただし、一般的に、問題は<iostream>ヘッダーの使用にあると思われます。これにより、かなり大きなライブラリがリンクされます。また、cout << xは単に印刷するだけではありません。ロケールやストリーム、そしてあらゆる種類の内部的なものがあります。

ただし、実行可能サイズを小さくすることが実際のミッションクリティカルな目的である場合は、それを避けてprintfまたはputsを使用してください。そうでない場合は、iostreamの1回限りのコストを支払い、それで完了します。

2
Kaz Dragon

Exeを作成した後は、いつでもexeで [〜#〜] upx [〜#〜] を実行できます。

2
SteveL

小さな実行可能ファイルが必要な場合、Tiny Cはprintf( "Hello world!")用に1536バイトの実行可能ファイルをコンパイルします。TinyCはCのみであり、C++ではなく、gccよりも高速にコンパイルされて低速の実行可能ファイルを提供することが知られています。

編集済み:cout <"Hello World!"を試しました。 DevC++(Mingw 4.8とIdeをバンドル)で、4,5MBの実行可能ファイルを入手しました!!

2
Antoni Gual Via

Msvc8のような他のコンパイラーやborlandc ++ 5.5.1のようなorderコンパイラーでさえ、非常に小さな実行可能ファイルを生成できるのに、mingw gccでは生成できないのはどうしてですか?

次の各ツールセットに対して「helloworld」のクイックコンパイルを実行し、コンパイルされた実行可能ファイルのサイズを確認しました。これらすべての場合において、ランタイムライブラリは静的にリンクされ、すべてのデバッグシンボルが削除されていることに注意してください。

compiler toolchain            exe size                   exe size
                              (w/iostream header)        (w/cstdio printf)
-------------------------------------------------------------------------
Borland C++ 5.5.1             110kbyte                    52kbyte
MSVC 2008 express             102kbyte                    55kbyte
MinGW- GCC 3.4.5              277kbyte                    <10kbyte
MinGW- GCC 4.4.1              468kbyte                    <10kbyte

興味深いのは、gcc 4.4.1の新しいバージョンでは、おそらくlibstdc ++のバージョンが異なるために、gcc3.4.5よりもさらに大きな実行可能ファイルが生成されることです。

では、mingwのリンクフェーズでデッドコードを削除する方法は本当にありませんか?

1
greatwolf

サイズの大部分は、かなり大規模なランタイムライブラリの使用に起因します。したがって、実際には、このような単純なアプリケーションを使用している場合、非常に大きな「デッドコード」をリンクしていることになります。

私の知る限り、リンクされたライブラリの未使用部分をスキップするリンカーフラグはありません。

小さなアプリケーションを偽造する方法は2つあります。

  1. ダイナミックリンクを使用します。次に、アプリケーションは動的にロードされたライブラリを参照します。それでもフルサイズ(実際にはそれ以上)が必要ですが、実行可能ファイルははるかに小さくなります。
  2. 実行可能圧縮 システムを使用します。
0
Niels Basjes