2012-01-07

oldnewthing: なんでHeapFreeがERROR_POSSIBLE_DEADLOCKで失敗するのか?

Why did HeapFree fail with ERROR_POSSIBLE_DEADLOCK? - The Old New Thing - Site Home - MSDN Blogs

ある顧客がassertに引っかかると報告してきた。何でも、HeapFree関数が、全く問題ないヒープブロックに対する操作に失敗し、GetLastError関数の結果は、ERROR_POSSIBLE_DEADLOCKだという。一体何がどうなっているのだ。

私の同僚が持ち前のエスパー能力を駆使して訊ねた。「ひょっとしてプロセスは終了中かい?」

「ええ、まあ。何で分かったんだい?」

プロセスはどのように終了するかという話を思い出して欲しい。まず最初に起こることは、プロセスの他のスレッドをすべて、強制的に終了させるのである。これにより、スレッドによって所有されていた同期リソースがロックされたままになる可能性がある。この場合、同期リソースとはヒープである。

ある関数がHeapFreeを呼んだ際、ヒープのコードはヒープをロックしようとするが、他のスレッドによって所有されているので、ロックできないことを検知する。そして、その他のスレッドはすでに終了しているのだ(他のスレッドはHeapFreeの操作の最中に強制終了される可能性がある)。ヒープのコードはこの状況を検知し、デッドロックを回避して、ERROR_POSSIBLE_DEADLOCKを返す。

これと同様に、プロセスの終了中に、メモリーを安全に確保することはできない。つまり、メモリーは確保も解放もできないのだ。前回学んだように、プロセスが終了中であるならば、クリーンアップなどすべきではないのだ。プロセスのアドレス空間が解放されるときに、メモリーはすべて解放される。手動で解放する必要はない。時間の無駄である。

Windowsにおいて、プロセスの終了中にリソースを解放する必要はない。この単純なルールを理解出来ないWindowsプログラマーは実に多い。そういうプログラマーの書いたコードは、プログラムの終了時にまぬけにも例外エラーを出したりする。

No comments: