異なる DLL 内の静的オブジェクトの破棄順序を強制するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/872143

  •  22-08-2019
  •  | 
  •  

質問

私は2つ持っています 静的 2 のオブジェクト 異なる DLL:

オブジェクト リソース (これはシングルトンです)、およびオブジェクト ユーザー. 。デストラクター内のオブジェクト ユーザーは、オブジェクト リソースにアクセスする必要があります。

オブジェクト User の前にオブジェクト Resource が破棄されないようにするにはどうすればよいですか?

役に立ちましたか?

解決

それらの対応するDLLがアンロードされたときに、

グローバルオブジェクトが破壊されます。あなたの「ユーザー」DLLは、あなたの「リソース」DLLのおそらく依存しているように、あなたが困っている:「リソースは」は常に「ユーザー」の前に破壊されます。

。 1が存在する場合は、

私は、また、この質問に良い答えによって興味があります。今まで、私はそれが終了する前にアプリケーションによって呼び出されなければならないクリーンアップ機能を使用している、と私は唯一のデストラクタに無害なコードを維持ます。

他のヒント

あなたが同じDLLにその2つのグローバル変数を置くことができる場合は、

それは同じ話ではありません。独自の応答でジェムによって語らとして、DLLのデタッチメント優しい無関心順序はシステムによって保証されていません。 2は、DLLを分離したとき、したがって、あなたは大きな問題がある可能性があります。私は、Windowsシステムの第一人者ではないけど、グーグルとの外観を持つ、私は、彼らはそれに対処するための無い優れたソリューションと同じ問題があった告げるMSDNブロガーを発見しました。

私、あなたはそのような場合には、あなたが(私の知る限り理解と解決できない)「garanteedないDLLのデタッチメント優しい無関心順」問題に対処する必要はありませんが、解決策は簡単です、私によると、1と同じDLLに入れすることができます。
グローバル変数の破壊の順序はC ++言語でgaranteedされていません。しかし、あなたはまだ新しい問題に対処する必要があります。しかし、この1つは対処することができます:

あなたは、参照coutingのいくつかの種類を使用する必要があります。ブースト:: shared_ptrのは、トリックを行うことがあります。

グローバルそれを宣言し、そのように定義します:

boost::shared_ptr my_resource_ptr ( new Resource() ); // new operator is important here!

次に、あなたのストアの独自のshared_ptrのにあなたのユーザーの実装を変更する必要があります

class User
{
    ...
    boost::share_ptr a_resource_ptr;
    ...
};

あなたのユーザーインスタンスのすべての1が破壊されない限り、これらのリソースのインスタンスを「保持」になり、そうprematuralyグローバルのshared_ptrが破壊されている可能性もかかわらず、削除されるのを防ぐ。
破壊される最後のUserインスタンスは、(undirectly)リソースインスタンスを削除します。

は、使用どのような参照カウント、ComPtr、あなた自身が、それはトリックを行う必要があります。

私はあなたが別のモジュールにあるグローバルの破壊の順序を変更することができるとは思いません。 いくつかの参照カウントを追加する任意のチャンス?

本当に 2 つの別々の DLL を取得したい場合は、いくつかのヒントがあるかもしれません。の使用を検討してもよいでしょう FreeLibrary() Windows APIから。が述べたように、 msdn FreeLibrary() カウンタが 0 に達するとアンロードされる Dll の参照カウンタをデクリメントします。

欠点:を使用して FreeLibrary() でロードしていることを意味します LoadLibrary() (msdn リンク)、このライブラリから関数を呼び出すと、 GetProcAddress() 関数を使用すると、非常に醜いコードが作成される可能性があります。また、各関数のアドレスを保存するために、Dll の関数を指すグローバル変数を取得するなど、コードにも何らかの変更が含まれる可能性があります。

それを実装したい場合:

  1. ライブラリをロードして解放する必要があります main() プロセスの機能、
  2. また、User クラスを実装する DLL からライブラリをロードして解放します。で実装します。 DllMain() この DLL の関数 (理由が次の場合) DLL_PROCESS_DETACH (見る mdsn の DllMain リンク.

したがって、「User」ライブラリがそれを終了した場合にのみ、「Resource」ライブラリをアンロードします。

よかったら試してみてください。私は実装したことがないので、うまくいくかどうか教えてください。

追伸:2 つの回答の両方を詳しく説明する際に、2 つの回答を意味のある区切りにするために、あなたの質問に対する 2 番目の回答を投稿しました。それらを混同して混乱しないでほしいのですが...

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top