DLL がアンロードされたときに呼び出される関数を作成する方法はありますか? 考えられることの 1 つは、DLL でグローバル オブジェクトを作成し、そのデストラクタにメモリ フリー コールを書き込むことです。
それは可能ですが、オブジェクトのデストラクタが呼び出される正確なタイミングは未定義になると思います。
に興味があるかもしれません。 でDLL_PROCESS_DETACH
重要なことを行うことは避けるべきですが、DllMain
ここではリソースの割り当てを解除しても問題ないようです。注意事項に注意してください。
DLL のロードの失敗、プロセスの終了、または FreeLibrary の呼び出しの結果として DLL がプロセスからアンロードされた場合、システムは、個々のスレッドの DLL_THREAD_DETACH 値を使用して DLL のエントリポイント関数を呼び出しません。プロセス。DLL には DLL_PROCESS_DETACH 通知のみが送信されます。DLL は、この機会を利用して、DLL に認識されているすべてのスレッドのすべてのリソースをクリーンアップできます。
DLL_PROCESS_DETACH を処理するとき、DLL が動的にアンロードされている (lpReserved パラメータが NULL である) 場合にのみ、DLL はヒープ メモリなどのリソースを解放する必要があります。プロセスが終了している場合 (lpvReserved パラメーターが NULL でない場合)、現在のスレッドを除くプロセス内のすべてのスレッドは、既に終了しているか、ExitProcess 関数の呼び出しによって明示的に終了されています。これにより、ヒープなどのプロセス リソースが残される可能性があります。矛盾した状態で。この場合、DLL がリソースをクリーンアップするのは安全ではありません。代わりに、DLL は、オペレーティング システムがメモリを再利用できるようにする必要があります。
DLL がメモリを保持できる理由を詳しく説明する必要がある場合があります。DLL によって作成された多数のオブジェクトがある場合は、定義されたライフサイクルがあり、ライフサイクルの終わりに自分自身をクリーンアップする必要があります。
それらがオブジェクトでない場合 (つまり、メモリが割り当てられ、関数を介して呼び出し元に返されている場合)、DLL を消費している人に責任を負わせてみませんか? 彼らはメモリを解放することができます。ターミナル サービス ライブラリは、このパターンに従います ( WTSFreeMemory
)。
リソースの寿命が長く、ライブラリの存続期間中存在する必要がある場合は、消費者がライブラリのライフサイクルを制御できるようにします。2 つの関数を記述します: MyFrameworkStartup
andMyFrameworkShutdown
必要に応じて。Winsock はこのパターン (WSAStartup
およびWSACleanup
) に従います。
私のもう 1 つのアイデアは、DLL がアンロードされたときにメモリを解放するためにオペレーティング システムに依存することですが、これは汚いようです。
プロセスが終了していれば問題ありません:
メモリの解放について心配する必要はありません。プロセスのアドレス空間が破壊されると、すべてなくなります。ハンドルを閉じる必要はありません。プロセス ハンドル テーブルが破棄されると、ハンドルは自動的に閉じられます。他の DLL は、すでに DLL_PROCESS_DETACH 通知を受け取っている可能性があるため、他の DLL を呼び出そうとしないでください。その場合、デストラクタの実行後に Delphi オブジェクトを使用しようとすると、Delphi オブジェクトが異常に動作するのと同じように異常に動作する可能性があります。 .
「何もしない」戦略を実行する前に、記事全体とコメントを読んで理解してください。