前回の日記で、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) ); }