私はC++プログラムに取り組んでおり、単一の1200行ファイル(かなり複雑なステートマシンを初期化する)からコンパイルされたオブジェクトコードは、ほぼ1メガバイトになります。何がファイルをこれほど大きくしているのでしょうか?オブジェクトファイル内のスペースを取るものを見つける方法はありますか?
7 に答える
オブジェクト ファイルが必要以上に大きくなる場合、いくつかの理由が考えられます。
- 依存ライブラリを静的に含める
- デバッグ情報を使用してビルドする
- プロファイリング情報を使用した構築
- テンプレートを使用して (非常に) 複雑なデータ構造を作成する (おそらく再帰的なブースト構造)
- コンパイル中に最適化フラグをオンにしない (あまり節約できず、極端に使用すると問題が発生する可能性があります)
最初に、デバッグ情報を使用してビルドしているかどうかを確認することをお勧めします。これは、私の経験では最も肥大化する原因となります。
(最適化とデッド コード ストリッピングがオンになっていると仮定しています)。
リンカーの「マップ ファイルの生成」オプションをオンにして、出力を調べます。
一般的な原因は、大量のコードを生成するマクロ/テンプレート、および大きなグローバル オブジェクトです。
おそらくいくつかのテンプレートのインスタンス化 (特にstd::iostream
s) と、大規模なインライン化 (つまり、ヘッダーで完全に定義されたクラス) かもしれません。しかし、そもそも 1 メガバイトのオブジェクト ファイルの問題点は何でしょうか。リンク中に、非常に小さなバイナリになる可能性があります。ここでは、たとえば 700 KiB バイナリにリンクされる 20 MiB のオブジェクト ファイルを含むプロジェクトを取得しました。
更新:大きな静的配列/オブジェクトの可能性もあります。それに加えて、MSVC++ と GCC では、生成されたファイルのアセンブリを確認できます。これにより、いくつかのヒントが得られます (GCC ではg++ -S foo.cpp
、MSVC++ では'/FAs'です)。多くのテンプレート インスタンスが表示される場合は、これらが理由です。そうでない場合は、オブジェクトのオブジェクト サイズstatic
です。
もう1つの考えられる理由は、VC++オプションであるリンク時コード生成です。これにより、コンパイラのバックエンドがリンカに移動します。これにより、より適切な最適化が可能になりますが、オブジェクトファイルには、通常フロントエンドとバックエンドの間で渡されるすべての内部データ構造が含まれている必要があります。
コンパイル時の値を確認するために使用するマクロを次に示します。
template <size_t N> struct compile_time_number { private: typedef int check; };
#define compiler_check_number(N) ((compile_time_number< N >::check)0)
次に、コンパイル時に満足して、どのシンボルがスペースを占めているかを確認します。
編集: 誰もこれを理解していないようなので、明確にします: これを使用する方法は、 を追加することcompiler_check_number(sizeof(<insert struct or global variable here>))
です。コンパイラは、変数または構造体のサイズをコンパイル時のエラーとして吐き出します。コードが巨大なオブジェクト ファイルの原因になることはほとんどありません。
私はこれを常に使用して、デバッガーを実行することなく物事がどれほど大きいかを確認しています。