Windows 秘話: EmulateHeap による思い出を辿る旅

Raymond Chen

Application Compatibility Toolkit には、EmulateHeap と呼ばれるごく単純な (ですが、かなり乱暴な) 互換性に関する動作があります。

プロセスで、この互換性の修正を有効にすると、OS レベルのすべてのヒープ関数が、Windows 95 のヒープの詳細をエミュレートする代替関数にリダイレクトされます (ヒープ関数には、HeapCreate、LocalLock、GlobalReAlloc などの関数が含まれます)。

たとえば、あるプログラムでは、2 つのメモリ ブロックを割り当てて、その両方を解放してから、別のメモリ ブロックを割り当てて、3 つ目のブロックで返されるポインターが、1 つ目のブロックで返されるポインターと数値的に同じであることに依存しているとします (これは、Windows 95 で行われる処理です)。

また、ヒープ バッファーをオーバーフローしても、ヒープ バッファーの後にあるメモリは使用されないので、深刻な状態に陥ることがないプログラムをお持ちかもしれません (これも Windows 95 で見られる現象です)。

メモリを解放して、しばらくしてから、解放したメモリにアクセスしたときに、メモリには解放したときの値が含まれており、他のメモリ割り当てで再利用されていないことを想定しているプログラムもあります。Windows 95 では、このようなメモリが再利用されることはありませんでした (さらに恐ろしいことに、このプログラムでは、特定の方法でメモリが解放された後に値が変更されることを想定しています)。

古いアプリケーションには、このように不可思議な依存関係が多数存在します。このような動作は散見されるもので、Windows 95 のヒープ マネージャーで実行した場合に、たまたま問題が発生しなかったので、問題にならなかっただけという些細な間違いです。このようなプログラムを Windows 95 以外のバージョンの Windows で実行すると、ヒープ マネージャーが異なるのでプログラムはクラッシュします。

このことは Windows 95 のヒープ マネージャーの優位性や堅牢性を示すものではありません。Windows 95 では、単に他のバージョンの Windows とヒープ マネージャーが異なるというだけのことです。Windows 95 で実行するとクラッシュするが Windows 7 で実行すると問題なく実行されるという動作も同じくらいあるでしょう。皆さんが目にしている動作は、自己選択的なものに過ぎません。1995 年に作成したプログラムには、Windows 95 で実行するとクラッシュするバグがあったかもしれませんが、そのバグに気付いて修正したのは、単にプログラムを Windows 95 で実行していたからです。

EmulateHeap という互換性の修正をプロセスで有効にすると、ヒープ マネージャーの動作は 1995 年当時の位置でメモリを調整するように変更されます。Windows 95 で発生していた偶発的な動作 (知らないうちにアプリケーションが依存していた動作) が、強制的に発生するようになり、このようなバグのあるアプリケーションは、以前と同じように実行されるようになります。断片化を抑える機能など、新しいヒープの機能では、古いアプリケーションが依存している偶発的な動作を変更するため、このような偶発的な動作を強制するということは、新しい機能は無効にする必要があるということになります。

単純な部分についての説明は以上です。

また、その理由もかなり乱暴なもので、Application Compatibility Toolkit の開発者が Windows 95 のヒープ マネージャーを完璧にエミュレートした方法は、Windows 95 のヒープ マネージャーのソース コードのコピーを単純に取り出して、再コンパイルし、互換性のインフラストラクチャに追加しただけというものです。つまり、Windows アプリケーションの互換性フレームワークには Windows 95 カーネルのコピーが大量に含まれています。Microsoft Bob をすべてコピーしたというわけではありませんが、Windows 95 から、そのままの状態で取り出したコードは、単なる安定器以上の役割を果たしています。EmulateHeap という互換性の修正をプロセスで有効にすると、昔のコードをハード ドライブから読み込んで処理を行えるようになります。

Windows 7 では、多くの単純な種類のアプリケーション ヒープのメモリ エラーを検出して、自動的にエラーを軽減するフォールト トレラント ヒープという新しいサブシステムが導入されました。たとえば、フォールト トレラント ヒープでは、二重解放、ヒープ バッファー オーバーラン (少なくとも小規模なオーバーラン)、解放した後にメモリを使用する操作 (少なくとも、メモリを解放した直後にメモリを使用する操作) を検出して修正します。この汎用的なソリューションにより、次期バージョンの Windows には Windows 7 のヒープ マネージャーを互換性インフラストラクチャのファイルに含める必要がなくなることを祈っています。

Raymond Chen は自分の Web サイト「The Old New Thing (英語)」および同じタイトルの書籍 (Addison-Wesley、2007 年) の両方で、Windows の歴史、Win32 プログラミングについて取り上げています。また、Zune のヘッドフォンを壊してしまったことについても触れています。

関連コンテンツ