Windows Vista と CreateWindow 限界

昨日はこのスクリーンショットを撮るための作業をしていたのですが,これが思いのほか大変な作業でした.

というのも,「Windows キー + E」を押しっぱなしで大量に Explorer を開けば楽勝かなとやってみたら,途中から中身のない Explorer が表示されるわ,デスクトップのコンテキストメニューが表示されなくなるわでかなり悲惨な状況になってしまいます.イベントログを読んでみると,どうやら CreateWindow API の呼び出しが失敗し始めているようでした.
このような現象としては,「Desktop Heap の枯渇」という問題が以前から知られています.「Microsoft Critical Problem Resolution (CPR) Platforms Team」の blog に最近ポストされた『Desktop Heap Overview』という記事が参考になるでしょう.ただし Windows Vista ではカーネル空間のアドレス構造がずいぶんと変化してしまったようで,同記事の内容は Vista には直接あてはめることはできないそうです.
最近のプログラマの多くがメモリ不足でオブジェクト生成が失敗する可能性を「非常にまれ」と考えているように,私も含めて近年の多くの Windows プログラマは CreateWindow が失敗する可能性をあまり真剣に考慮していないと考えられます.メモリ不足で例外を発生させるモダンなフレームワークと違って,CreateWindow の戻り値をチェックしないでいるとウィンドウの生成に失敗してもそのままプロセスは動き続けてしまいます.たとえばウィンドウ生成が成功していれば無害な処理が,ウィンドウ生成に失敗した場合は破壊的な影響を及ぼし続けるかもしれません*1
結局,実験に Explorer を使うのは諦めて,Visual C++ 2005 を起動して 1024×1024 のシンプルなウィンドウを作成するプログラムを作ました.そのプログラムを数十回起動したところで,DWM は想定通りデスクトップコンポジションをオフにしてくれて,無事に上のスクリーンショットを撮ることができました.このように DWM チームは自分たちの責任の範囲内で良い仕事をしてくれているのですが,今回のように VRAM 以外のリソースが先に枯渇してしまう可能性があるために,全体としてはまだまだ暗黒の時代が続きそうですね.

*1:Unix 系のシステムで,ちょっとした冗談からプロセステーブルを枯渇させたことがある人は,似たような楽しい世界を見たことがあるでしょう.