17
test.c:

int main()
{
    return 0;
}

私はフラグを使用していません(私はgccの初心者です)、コマンドだけです:

gcc test.c

私はwin32でGCCの最新のTDMビルドを使用しました。結果の実行可能ファイルはほぼ23KBで、空のプログラムには大きすぎます。

実行可能ファイルのサイズを減らすにはどうすればよいですか?

4

10 に答える 10

39

その提案に従わないでください、しかし娯楽のために、可能な限り最小のELFバイナリを作ることについてのこの「物語」を読んでください。

于 2009-08-22T13:48:17.807 に答える
21

サイズを小さくするにはどうすればよいですか?

  • しないでください。あなたはただあなたの時間を無駄にしています。
  • -sフラグを使用してシンボルを削除します(gcc -s)
于 2009-08-22T13:08:16.247 に答える
12

デフォルトでは、実行可能ファイルにリンクされているいくつかの標準ライブラリ(Cランタイムなど)。詳細については、キー--nostdlib --nostartfiles --nodefaultlibを確認してください。ここで説明するリンクオプション。

実際のプログラムの場合、2番目のオプションは、-Os(サイズを最適化)などの最適化オプションを試すことです。

于 2009-08-22T13:08:08.603 に答える
12

あきらめる。 x86 Linuxでは、gcc4.3.2は5Kバイナリを生成します。ちょっと待って!それはダイナミックリンクです!静的にリンクされたバイナリは、半分以上のメガです:516K。リラックスして、膨満感と一緒に暮らすことを学びます。

そして彼らは、Modula-3は200K hello worldバイナリのためにどこにも行かないだろうと言いました!


何が起こっているのか不思議に思うかもしれませんが、Gnu Cライブラリは、プログラムがそれらに依存しているかどうかに関係なく、特定の機能を含むように構成されています。これらの機能には、mallocやfree、dlopen、文字列処理などの雑学クイズや、ロケールや国際化に関係していると思われる大量のコンテンツが含まれますが、関連するマニュアルページは見つかりません。

最小限のサービスを必要とするプログラム用に小さな実行可能ファイルを作成することは、glibcの設計目標ではありません。公平を期すために、これまでに使用したすべてのランタイムシステム(約5ダース)の設計目標でもありませんでした。

于 2009-08-22T18:59:12.767 に答える
9

実際、コードが何もしない場合でも、コンパイラーが実行可能ファイルを作成するのは公平ですか?;-)

ええと、Windowsでは、実行可能ファイルのサイズはかなり小さいかもしれませんが、それでもサイズはあります。古いMS-DOSシステムでは、完全な何もしないアプリケーションはほんの数バイトになります。(プログラムを閉じるために21h割り込みを使用するのに4バイトだと思います。)次に、これらのアプリケーションはメモリに直接ロードされました。EXE形式が普及すると、状況は少し変わりました。これで、実行可能ファイルには、コードとデータセグメントの再配置に加えて、いくつかのチェックサムとバージョン情報など、プロセス自体に関する追加情報が含まれていました。Windowsの導入により、フォーマットに別のヘッダーが追加され、Windowsで実行する必要があるため、実行可能ファイルを実行できなかったことをMS-DOSに通知しました。そして、Windowsは問題なくそれを認識します。もちろん、実行可能形式もビットマップなどのリソース情報で拡張されました。

何もしない実行可能ファイルのサイズは、コンパイラーとそのサイズを縮小するために使用したすべてのメソッドに応じて、現在4〜8キロバイトになります。これは、UPXが実際に実行可能ファイルを大きくするサイズになります。コードに特定のライブラリを追加したため、実行可能ファイルに追加のバイトが追加される場合があります。特に、初期化されたデータまたはリソースを備えたライブラリは、かなりの量のバイトを追加します。デバッグ情報を追加すると、実行可能ファイルのサイズも大きくなります。

しかし、これはすべてサイズを縮小する上で優れた演習になりますが、アプリケーションの肥大化について心配し続けることが実際的かどうか疑問に思うかもしれません。最新のハードディスクはファイルをセグメントに分割し、非常に大きなディスクの場合、その差は非常に小さくなります。ただし、これらの最適化に慣れている専門の開発者でない限り、サイズをできるだけ小さく保つために必要な問題の量は、開発速度を遅くします。これらの種類の最適化はパフォーマンスを向上させる傾向がなく、ほとんどのシステムの平均ディスク容量を考慮すると、なぜそれが実用的であるかわかりません。(それでも、私は同様の方法で自分のコードを最適化しますが、それでも、これらの最適化の経験があります。)


EXEヘッダーに興味がありますか?それは「マーク・ズビコフスキー」の文字MZで始まります。最初の部分は、実行可能ファイル用の古いスタイルのMS-DOSヘッダーであり、プログラムがMS-DOS実行可能ファイルではないことを示すMS-DOSへのスタブとして使用されます。(バイナリには、「このプログラムはDOSモードでは実行できません。」というテキストがあります。これは基本的にすべてのメッセージを表示します。次はPEヘッダーで、WindowsがMS-DOSの代わりに認識して使用します。ヘッダー。PortableExecutableの場合はPEという文字で始まります。。この2番目のヘッダーの後に、実行可能ファイル自体があり、コードとデータのいくつかのブロックに分割されています。ヘッダーには、特定のブロックをロードする場所をOSに指示する特別な再割り当てテーブルが含まれています。そして、これを制限することができれば、最終的な実行可能ファイルは4 KB未満になる可能性がありますが、その場合、90%はヘッダー情報であり、機能はありません。

于 2009-08-22T13:44:09.590 に答える
3

DJGPPFAQが何年も前にこれに対処した方法が好きです。

一般に、「Hello」プログラムのサイズを見てコードサイズを判断することは、そのようなプログラムがほとんどスタートアップコードで構成されているため、意味がありません。...これらすべての機能の能力のほとんどは、「Hello」プログラムで無駄になります。15バイトの文字列を出力して終了するためだけに、そのすべてのコードを実行しても意味がありません。

于 2009-08-22T13:48:33.127 に答える
2

この演習の目的は何ですか?

Cのように低レベルの言語であっても、mainを呼び出す前に行わなければならないセットアップはまだたくさんあります。そのセットアップの一部はローダー(特定の情報を必要とする)によって処理され、一部はmainを呼び出すコードによって処理されます。そして、通常のプログラムに必要なライブラリコードが少しあるでしょう。少なくとも、dllにある場合は、おそらく標準ライブラリへの参照があります。

空のプログラムのバイナリサイズを調べること自体は、価値のない演習です。それはあなたに何も教えてくれません。コードサイズについて何かを学びたい場合は、空でない(できれば自明でない)プログラムを書いてみてください。標準ライブラリを使用するプログラムと、すべてを自分で実行するプログラムを比較します。

そのバイナリで何が起こっているのか(そしてなぜそれがとても大きいのか)を本当に知りたい場合は、実行可能形式を見つけてバイナリダンプツールを入手し、それを分解してください。

于 2009-08-22T13:46:33.423 に答える
2

' size a.out'は、コード、データ、およびbssセグメントのサイズについて何を教えてくれますか?コードの大部分は、o / sによって呼び出され、呼び出す前に(コマンドライン引数をargc、argvにソートするなどの)作業をセットアップするスタートアップコード(通常crt0.oはUnixマシン上)である可能性がありmain()ます。

于 2009-08-24T22:28:05.863 に答える
1

シンボルを取り除くためにバイナリでstripを実行します。gccバージョン3.4.4(cygming special)では、10kから4Kにドロップします。

カスタムランタイム(mainを呼び出す部分)をリンクして、ランタイム環境をセットアップしてみてください。すべてのプログラムは同じものを使用してgccに付属するランタイム環境をセットアップしますが、実行可能ファイルにはデータやゼロ化されたメモリは必要ありません。つまり、memset / memcpyなどの未使用のライブラリ関数を取り除き、CRT0のサイズを小さくすることができます。この情報を探すときは、組み込み環境のGCCを見てください。一般に、カスタムランタイム環境を使用するのは組み込み開発者だけです。

残りは、実行可能ファイルをロードするOSのオーバーヘッドです。手で調整しない限り、そこにはあまり行きませんか?

于 2009-08-24T08:02:25.413 に答える
0

GCCを使用して、他の最適化フラグ(または)-Osの1つではなく、を使用してプログラムをコンパイルします。これは、速度ではなくサイズを最適化するように指示します。ちなみに、重要なセグメントがうまく適合している場合は、速度の最適化よりもプログラムの実行速度が速くなることがあります。一方、実際にはコードサイズの増加を引き起こす可能性があります。-O2-O3-O3

また、最終的なバイナリから未使用のコードを除外するように指示するリンカーフラグがいくつかある場合もあります。

于 2009-08-22T14:10:24.480 に答える