前回の日記で、Low fragmentation heapによって同じReleaseビルドでも挙動が変わる!という話をしましたが、こんなことWindows XPの時にはなかったような気がして、ちょっと調べてみました。
まず、Windows7の環境では以前の日記と同じく、デバッガが繋がっているときにはLFH(Low fragmentation heap)がONにならず、単独実行させたときにはLFHがONになるという状況でした。一方XPでは、このような挙動が起こるのかを調べてみると、デバッガの接続状態にかかわらずヒープの種類は変化しませんでした。このときのヒープの種類は Look aside listヒープというもののようです。
| OS | ヒープ | デバッガ |
|---|---|---|
| Windows7 | Regular Heap | デバッガ有 |
| Windows7 | LFH | デバッガ無 |
| WindowsXP | Look aside list Heap | デバッガ有 |
| WindowsXP | Look aside list Heap | デバッガ無 |
確かWindowsXPであれば、LFHを有効にも出来たはずなので、そのコードを埋め込んで再度テストしてみます。
| OS | ヒープ | デバッガ |
|---|---|---|
| WindowsXP | Look aside list Heap | デバッガ有 |
| WindowsXP | LFH | デバッガ無 |
予想通り、デバッガが繋がっているとLFHが有効になりません・・・。
そこで、ヒープデバッグを無効化する _NO_DEBUG_HEAP を “1”にセットして再度チャレンジしてみます。
念のため、この環境変数をユーザー環境変数としてセットして、再起動を行っておきます。
この状態で再度、先ほどと同じように LFHをプログラム内部で有効にして、ヒープ状態を取得してみます。
| OS | ヒープ | デバッガ |
|---|---|---|
| WindowsXP | LFH | デバッガ有 |
| WindowsXP | LFH | デバッガ無 |
この結果を見ると、Windows XP(SP3)の環境でもデバッガ有りの状態で LFHを有効化することができました!
まとめ
以上のことをまとめると、常にLow-fragmentation heapを使いたい場合には、_NO_DEBUG_HEAP=1をセットしておいて、WindowsXPのときにはLFHを有効にするコードを実装しておく、ということで対処できるようです。
ただ、_NO_DEBUG_HEAPをセットしての運用はちょっと怖いので、開発時のマシン環境だけに限定したいですね。
おまけ
調べればすぐにわかりますが、Low fragmentation heapを有効にするコードを下記に記しておきます。
プログラム中で使用しているヒープ全てにおいてLFHのフラグをセットしてまわります。
// HeapをLFHフラグを設定
HANDLE heaps[10];
DWORD heapCount = ::GetProcessHeaps( 10, heaps );
for( DWORD i = 0; i < heapCount; ++i ) {
ULONG HeapFlagVal = 2; // LFH
HeapSetInformation(
heaps[i],
HeapCompatibilityInformation,
&HeapFlagVal,
sizeof(HeapFlagVal) );
}
