0

Linux の C++ 共有ライブラリに奇妙な問題があります。

このプロセスはライブラリを 2 回ロードおよびアンロードします (これは設計によるものであり、変更できません)。

  1. 最初の dlopen() で、ライブラリ内のすべての静的メンバーが正しい順序で初期化されます。
  2. 次に、最初の dlclose() が呼び出されると、破壊も期待どおりに、構築とは逆の順序で行われます。
  3. 2 回目の dlopen() では、すべて問題ありません。最初と同じように、構築の順序は正しいです。
  4. しかし、2 番目の dlclose() で、破棄の順序が突然破られます。デストラクタは、初期化されたときと同じ順序で呼び出され、静的オブジェクトがすでに破棄されたオブジェクトにアクセスしようとすると、SEGFAULT が発生することがよくあります。
  5. その後 dlopen()/dlclose() を試みると、3 番目と 4 番目のステップが正確に繰り返されます。

最小限の例で問題を再現しようとしましたが、成功しませんでした.小さな偽の共有ライブラリでは、すべてが期待どおりに機能します. 私の大きなライブラリには、2 番目の dlclose() で大混乱を引き起こすものがあり、それは非常に大きいです。

gcc (3.2/3.4/4.1.2 を試した) や Linux ディストリビューション (RHEL 4/5、SuSE 10) への依存関係は見つかりませんでした。Web で同様のケースを検索すると、0 件の結果が得られました。類似したケースはありません。

実験中、atexit() ハンドラーの順序が影響を受けるかどうかを確認するために、atexit() へのいくつかの呼び出しを静的オブジェクト コンストラクターに埋め込もうとしましたが、影響があることがわかりました。手順 1/2/3 は正常に機能します (dlopen/dlclose/dlopen)。2 番目の dlclose では、atexit に登録されたハンドラーの順序が正しくありません。

答えが得られるとはあまり期待していませんが、問題を追求する方法についての提案をいただければ幸いです。

前もって感謝します、

アンドリュー・シェティニン

PS Update - GLIBC で atexit() のコードをデバッグしたところ、ヒットしているバグがあることがわかりました。実際には非常に単純なバグです。GLIBC 2.4 で修正されましたが、GLIBC 2.3.4 で作業できなかったのは不運でした。

4

2 に答える 2

3

これは、GLIBC 2.4 で修正された GLIBC 2.3.x のバグです。

このバグは、非常に特殊な条件下でトリガーされます。つまり、プロセスが、異なるオブジェクト ファイルに多数の静的変数を含む C++ ライブラリを複数回開いたり閉じたりした場合です。

atexit() エントリは、32 個のハンドラー ポインターの配列の単一リンク リストに編成され、atexit() の古いコードは、新しいハンドラーを単一リンク リストの間違ったページに挿入したため、ファイナライズを呼び出す atexit() 契約が破られました。登録の逆順でハンドラを登録します。

于 2011-11-15T08:53:15.190 に答える
0

私はあなたが想像力の範囲によって静的なctor/dtorの順序に依存するかもしれないとは思わない。保証は提供されません。

それぞれ1回だけ呼び出すセットアップ関数とティアダウン関数が表示されることを期待しています。これを一度行うことを確認するのはあなたの責任です。

于 2011-11-08T23:38:28.583 に答える