正式にはアンロードされていないのにメモリ上に存在しなくなったDLL
この記事では、DLLが正式にアンロードされていないにもかかわらず、メモリ上から消失してしまうという不可解な現象について解説しています。この問題は、DLLの参照カウントや読み込み/解放のタイミングに関する複雑な挙動に起因して発生する可能性があり、デバッグが困難なバグの原因となり得ます。
背景メモ
- この記事は、Windowsプログラマー向けに長年コラムを執筆してきたRaymond Chen(マイクロソフト社員)による「The Old New Thing」ブログの一篇。彼の記事は、一見不可解なWindowsの動作を、内部構造を踏まえて解説することで知られる。
- ここで扱われているのは「DLLが明示的にアンロードされていないのに、メモリ上から消えている」という問題。WindowsではFreeLibraryを呼ばなくても、複数スレッドでDLLが同時に使われ、最後の参照が解除されたタイミングでカーネルが自動的にDLLをメモリから解放する仕組みがある(DLLの内部参照カウント)。
- DLLの「存在」はプロセスのアドレス空間上にあることだが、そのDLLのコードを実行中のスレッドがあると、カーネルは内部の未解決参照(未完了のAPI呼び出しなど)がゼロになるまでDLLを生かしておく。この点を理解せずにデバッグすると、DLLがまるで幽霊のように消えたように見える。
- WindowsのDLLローディング/アンローディングの正確な動作は、プロセス内の全スレッドの状態とカーネル内の参照カウントに依存する。FreeLibraryの有無だけでは判断できない。