8

ファイルに含まれる単純な静的ライブラリを作成しました.a。さまざまなプロジェクトで使用する可能性がありますが、そのうちのいくつかは単純に 90% を必要としません。たとえば、ライブラリの一部であるニューラル ネットワークを AVR マイクロコンピューターで使用したい場合、おそらく他の多くのものは必要ありませんが、それがコード内でリンクされて、かなり大きなファイルが生成される可能性はありますか?

次のようなプログラムをコンパイルするつもりです。

g++ myProg.cpp myLib.a -o prog

4

4 に答える 4

1

GNU リンカは、オブジェクト ファイルごとに指定したライブラリから必要なものを取り込みます。GNU リンカに関する限り、オブジェクト ファイルはアトミック ユニットです。それらを分割しません。オブジェクト ファイルが 1 つ以上の未解決の外部参照を定義している場合、リンカはオブジェクト ファイルを取り込みます。そのオブジェクト ファイルには、外部参照が含まれている場合があります。リンカーはこれらを解決しようとしますが、解決できない場合、リンカーはそれらを解決する必要がある参照のセットに追加します。

実行可能ファイルが必要以上に大きくなる可能性がある問題がいくつかあります。必要以上に大きいとは、プログラムの実行中に決して呼び出されない関数、検査も変更もされないグローバル オブジェクトを含む実行可能ファイルを意味します。到達できないバイナリ コードが表示されます。

これらの問題の 1 つは、オブジェクト ファイルに多数の関数またはグローバル オブジェクトが含まれている場合に発生します。あなたのプログラムはこれらのうちの 1 つしか必要としないかもしれませんが、オブジェクト ファイルはリンカーにとってアトミック ユニットであるため、実行可能ファイルはそれらすべてを取得します。これらの追加の関数には、これらの関数への呼び出しパスがないため到達できませんmainが、実行可能ファイルには残っています。これが起こらないようにする唯一の方法は、「ソース ファイルごとに 1 つの関数」という規則を使用することです。私自身はその規則には従いませんが、その論理は理解しています。

ポリモーフィック クラスを使用すると、別の問題が発生します。コンストラクターには、自動生成されたコードと、コンストラクター自体の本体が含まれています。その自動生成されたコードは、親クラスのコンストラクターを呼び出し、オブジェクト内のクラスの vtable へのポインターを挿入し、初期化子リストに従ってデータ メンバーを初期化します。これらの親クラス コンストラクター、vtable、および初期化子リストを処理するメカニズムは、リンカーが解決する必要がある外部参照である可能性があります。親クラスのコンストラクターがより大きなヘッダー ファイルにある場合は、そのすべてを実行可能ファイルにドラッグしただけです。

vtableはどうですか?GNU コンパイラは、vtable を格納する場所としてキー メンバー関数を選択します。そのキー関数は、インライン定義を持たないクラスの最初のメンバー関数です。そのメンバー関数を呼び出さなくても、実行可能ファイルにそれを含むオブジェクト ファイルを取得し、そのオブジェクト ファイルがドラッグするすべてのものを取得します。

ソース ファイルを小さなサイズに抑えることで、この「猫が引きずり込んだものを見てください!」という問題を解決できます。問題。そのキー メンバー関数を含むファイルに特に注意を払うことをお勧めします。少なくとも猫が引きずり込むようなものに関しては、そのソース ファイルを小さくしておいてください。私はそのソース ファイルに小さな自己完結型のメンバー関数を入れる傾向があります。必然的に他の多くのものをドラッグする関数は、そこに行くべきではありません。

vtable のもう 1 つの問題は、クラスのすべての仮想関数へのポインターが含まれていることです。これらのポインターは、実際のものを指している必要があります。実行可能ファイルには、クラスに対して定義されたすべての仮想関数を定義するオブジェクト ファイルが含まれます。これには、決して呼び出さないものも含まれます。そして、これらの仮想関数が引き込むものもすべて取得します。

この問題の解決策の 1 つは、巨大なクラスを作成しないようにすることです。彼らはすべてを引きずり込む傾向があります。特に神のクラスは、この点で問題があります。もう 1 つの解決策は、関数を本当に仮想にする必要があるかどうかをよく考えることです。いつか誰かがそれをオーバーロードする必要があると思うからといって、単に関数を仮想化しないでください。これは投機的一般性であり、仮想関数を使用すると、投機的一般性には大きな代償が伴います。

于 2012-09-29T13:41:24.553 に答える