web-dev-qa-db-ja.com

STLを複数の共有ライブラリに静的にリンクすることの何が問題になっていますか?

ここにシナリオがあります:

  1. libA.soとlibB.soはどちらも同じSTLに静的にリンクしています。
  2. libA.soには、std :: stringを返すパブリックAPIがあります。
  3. libB.soはこの関数を呼び出し、文字列のコピーを受け取ります。
  4. 文字列のlibB.soのコピーがスコープ外になると、文字列のデストラクタが呼び出されます。
  5. コピーされた文字列を解放しようとするアプリケーションセグメントエラー。

このように静的にリンクすることは悪いことを他の場所で読んだことがありますが、なぜそれが悪いのかをもっと理解したいと思います。上記のシーケンスがクラッシュする理由を誰かが説明できますか?

8
user1509041

これについて非常に注意深く考えましょう。 libA.soはSTLと静的にリンクされています。ただし、STLは単独では存在せず、Cランタイム(CRT)が必要です。どちらもlibstdc ++。a静的ライブラリにあります。これは、libA.soとlibB.soが別々のCRTデータ構造を持っていることを意味します。特に、libA.soが使用するヒープは、libB.soが使用するヒープとは異なります。 libAのランタイムヒープから文字列を割り当て、libBのランタイムから解放しようとしても、libBのランタイムには文字列を割り当てるレコードがないため、単に機能しません。文字列を正しく破棄する唯一の方法は、libA.so内のデストラクタを呼び出すことです。

質問するかもしれませんが、libB.soは文字列のコピーを受け取りますよね?はい、そうですが、誰がこのコピーを割り当てましたか? libAのランタイムのコンテキスト内でコピーコンストラクターを使用して割り当てられています。

それでも、libB.soの文字列は引き続き使用できます。そこから破壊することはできません。

LibBに文字列へのポインターを受信させ、libBのランタイムのコンテキスト内でそのコピーを作成することもできます。そのコピーはlibBによって破壊される可能性があります。

そしてそれが静的リンクが時々悪い理由です。

8
Hadi Brais

STLはいわゆる「ステートフル」(「ステートレス」とは反対)で、内部に静的なものがあることを意味します。 STLをlibA.soとlibB.soの両方に静的にリンクすると、実行時にメモリにSTLライブラリの2つのインスタンスが取得されます(静的なものの2つのコピーを使用)。これらの2つのコピーはそれぞれ、割り当てられたリソースを個別に管理し、ライブラリの1つのインスタンスに割り当てられたリソースを別のインスタンスで解放することはできません

3
mvidelgauz