31

少なくとも Linux と Solaris では、静的ライブラリは実際にはコンパイル済みの .o を 1 つの大きなファイルにまとめたものにすぎません。スタティック ライブラリをコンパイルする場合、通常 -fpic フラグは省略されるため、生成されるコードは位置に依存します。

ここで、静的ライブラリが B であるとします。これをビルドして、結果の .a ファイルを作成しました。これは、位置に依存するすべての .o ファイルの単なるグロブです。今、ビルドしたい共有ライブラリ A があり、B を静的にリンクさせたいと考えています。A をビルドするときは、当然、-fpic フラグを使用して、生成されたコードの位置を独立させます。しかし、B に対してリンクすると、位置依存のオブジェクト ファイルと位置非依存のオブジェクト ファイルが混在していませんか?

-mimpure-text も指定しないと、テキストの再配置エラーが多く発生します。おそらくこれが原因だと思います。ライブラリをコンパイルするとき、共有バージョン、静的バージョン、共有ライブラリで使用できる静的バージョンの3回コンパイルする必要があるようです。私は正しいですか?-mimpure-text を使い続けることもできますが、g++ のマニュアル ページには、そうするとオブジェクトが実際に共有されないことが示されています (すべてが共有されていないのか、それとも静的にリンクされた部分だけなのかは不明ですが、誰か知っていますか?) .

4

3 に答える 3

29

共有オブジェクトで PIC コードを使用する必要はありません (-mimpure-text オプションを使用して許可できることを発見したため)。

とはいえ、共有オブジェクトの非 PIC コードはより重いです。PIC コードでは、メモリ内のテキスト ページは、ディスク上のテキスト ページの直接メモリ マッピングにすぎません。これは、複数のプロセスが共有オブジェクトを使用している場合、メモリ ページを共有できることを意味します。

ただし、PIC コードがない場合は、実行時リンカーが共有オブジェクトを読み込むときに、テキスト ページにフィックスアップを適用する必要があります。これは、共有オブジェクトを使用するすべてのプロセスが、修正されたテキスト ページの独自のバージョンを持つことを意味します (たとえ共有オブジェクトがコピー オン ライトと同じアドレスにロードされていても、ページが変更されたことに気付くだけです)。変更されたものであり、同じ方法で変更されたわけではありません)。

私にとって重要な問題は、それぞれが共有オブジェクトをロードする複数のプロセスを同時に実行するかどうかです。その場合は、SO 内のすべてのコードが PIC であることを確認する価値があります。

しかし、そうではなく、1 つのプロセスだけが共有オブジェクトをロードしている場合は、それほど重要ではありません。

于 2009-10-19T17:35:56.277 に答える
3

スタティック ライブラリの共有オブジェクト ライブラリ バージョンのリンク ステージで、次のことを行います。--whole-archive は、(リストの) 静的ライブラリ (libstatic.a の形式) 内のすべてのオブジェクトをリンクするため、(リスト) の前に -fPIC を指定するだけで、OP が行う必要があると思います。

于 2012-06-09T19:04:20.213 に答える
1

別のアプローチとして、2 つのライブラリを出荷します。共有ライブラリと、リンクしている静的ライブラリです。最終的な実行可能ファイルに正しくリンクする必要があります。

于 2009-10-19T18:40:12.607 に答える