2009-10-19 7 views
26

少なくともLinuxとSolarisでは、静的ライブラリは実際にコンパイルされた.oの束を1つの大きなファイルに投げ込んでいるだけです。静的ライブラリをコンパイルする場合、通常は-fpicフラグが指定されないため、生成されるコードは位置に依存します。共有ライブラリをスタティックライブラリにリンクする:アプリケーションがリンクしていた場合とは異なるスタティックライブラリをコンパイルする必要がありますか?

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

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

+0

最初の段落で '-fpic'を省略して位置依存コードにして、それを第2段落で使用して、位置に依存しないコードにしています。 –

答えて

24

共有オブジェクトでPICコードを使用する必要はありません(これを可能にするには-mimpure-textオプションを使用できます)。

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

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

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

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

+0

実際に、1つのプロセスだけがプロセスをロードしようとしていることがわかっていると、picなしでコンパイルするとパフォーマンス上のメリットはありませんか?レジスタを保存するためです。 –

+1

@JosephGarvin PICは32ビットx86コードではレジスタを消費しますが、64ビットコードではレジスタを消費しません。 x64命令セットは、現在実行中の命令の次の命令のメモリアドレスからオフセットしたNNNNバイトのデータをロードするプログラムカウンタ相対アドレッシングをサポートしています。x64のPICコードはGOTポインタレジスタを必要としません。 – dthorpe

+0

すばらしい説明をありがとう! – rkellerm

1

別の方法として、2つのライブラリを共有することができます.1つは共有し、もう1つは静的にリンクします。最終的な実行可能ファイルに正しくリンクする必要があります。

3

私は静的ライブラリの共有オブジェクトライブラリバージョンのリンクステージで次のことを行います:g ++ -shared -o libshared.so -Wl、-alip-archive -fPIC -lstatic -Wl、-no-全アーカイブ。 --whole-archiveは静的ライブラリ(libstatic.aの形式)内のすべてのオブジェクトをリンクしているので、-fPICを使って(リスト)するのはOPの必要なすべてです。

+0

あなたはもっと明確に説明できますか? – gyro

関連する問題