64ビットCPUでは当然のことながら、32ビットCPUと比べてはるかに広大な仮想アドレス空間を扱うことが出来ます。簡単なプログラムで、この広大なアドレス空間を堪能してみましょう。
(本記事の初稿は2005年です。64ビットCPUが普及した現在でも有用な内容と思われるので、そのままの内容で公開します。)
■CPUとOS上でのアドレス空間
本題に入る前に、アドレス空間についてまとめておきます。64-bitのプロセス(Long mode(IA32e mode))で扱える物理アドレスと仮想アドレスは以下のようになります。
物理アドレス空間:52-bit(1PB)。ただし現時点では40-bit(1TB)に制限されている。 仮想アドレス空間:48-bit(256TB)
物理アドレス空間:35-bit(32GB)もしくは40-bit(1TB) 仮想アドレス空間(1つのプロセス全体(USER+SYSTEM)):44-bit(16TB) 仮想アドレス空間(1つのプロセス(USERのみ)):43-bit(8TB)
仮想アドレス空間が64-bitとなっていませんが、これらは実装上のサイズです。Win64ではポインタはすべて64-bitです。(この場合上位16ビット(bits 63-48)は、有効なビット(bits 47-0)の最上位ビット(bit 47, MSB(Most Significant Bit)と呼ぶ)の値で埋めておきます。これをCanonical Address Formと呼びます。ポインタとして有効なのは下位48ビットのみです。)比較用に32-bit環境についても記します。
物理アドレス空間:32-bit(4GB)。PAE(Physical Address Extension)使用時は36-bit(64GB)。 仮想アドレス空間:32-bit(4GB)
物理アドレス空間:32-bit(4GB)。boot.iniに/PAE指定時は36-bit(64GB)(※1) 仮想アドレス空間(1つのプロセス全体(USER+SYSTEM)):32-bit(4GB) 仮想アドレス空間(1つのプロセス(USERのみ)):31-bit(2GB)。boot.iniに/3GB指定時は3GB利用することも可能。(※2) ※1 Physical Address Extension(PAE): 32-bitのCPUで36-bitの物理メモリを扱うための(CPU側の)仕組み。 より大量の物理メモリを扱えるので、スワップアウト回数軽減などの効果を期待できる。 ユーザープロセスには直接は影響しない。(仮想アドレス空間(USER)が広くなるわけではない。) ※2 4GT RAM Tuning: プロセスに(2GBでなく)3GBの仮想アドレス空間を与えるための(Windows側の)仕組み。 ※3 Address Windowing Extensions(AWE): 4GBを超える大量のメモリを1つのプロセスで扱うための(Windows側の)仕組み。(APIが提供される。) 仮想アドレス空間(USER)が広くなるわけではない。仮想アドレス空間内の領域を通して、 ページを切り替えながらメモリを読み書きする。 (MS-DOS全盛時代に一世を風靡したEMS(Extend Memory Specification)に似ている。 EMM386が懐かしい...)
■32-bitと64-bitで比較
さっそくプログラミングして試してみます。やることは2つです。
まずGlobalMemoryStatus()を用いて、プロセス内で使える(メモリを割り当ててもらえる)仮想アドレス空間の空きサイズを調べます。次に、サイズを増やしながら、VirtualAlloc()とVirtualFree()を用いてメモリの確保と解放を繰り返し、これをメモリ確保に失敗するまで繰り返し、果たしてどれだけのメモリを一括で確保できるのかを調べます。どれだけの仮想アドレス空間を一括で確保できるのかを調べるのが目的なのでメモリ確保の際にコミット(物理メモリもしくはページングファイルの割り当て)はせずに、予約するだけにします。
#include <windows.h> #include <stdio.h> #include <tchar.h> #define MEGA (1024*1024) #define GIGA (1024*1024*1024) void main(void){ MEMORYSTATUS memstat; SIZE_T mem_size, inc_size; DWORD flAllocationType; DWORD flProtect; DWORD dwFreeType; LPVOID baseadr, baseadr2; // GlobalMemoryStatus()で仮想アドレス空間の空きを調査 memstat.dwLength=sizeof(MEMORYSTATUS); GlobalMemoryStatus(&memstat); #ifndef _WIN64 // for Win32 _tprintf(TEXT("[Win32]Available virtual address space is %u MB.\n"), memstat.dwAvailVirtual/MEGA); #else // for Win64 _tprintf(TEXT("[Win64]Available virtual address space is %I64u GB.\n"), memstat.dwAvailVirtual/GIGA); #endif // サイズを増やしながら、メモリの予約・解放を繰り返す #ifndef _WIN64 // for Win32 mem_size=MEGA; // 初期値は1MB inc_size=MEGA; // IMBずつ増やす #else // for Win64 mem_size=GIGA; // 初期値は1GB inc_size=GIGA; // 1GBずつ増やす #endif while(1) { flAllocationType=MEM_RESERVE; flProtect=PAGE_READWRITE; baseadr=VirtualAlloc(NULL,mem_size,flAllocationType,flProtect); if(baseadr!=NULL) { baseadr2=baseadr; dwFreeType=MEM_RELEASE; VirtualFree(baseadr, 0, dwFreeType); mem_size+=inc_size; } else { mem_size-=inc_size; break; } } // END of while() #ifndef _WIN64 // for Win32 _tprintf(TEXT("[Win32]Lump reservation of %u MB is OK. Address is %p.\n"), mem_size/MEGA, baseadr2); #else // for Win64 _tprintf(TEXT("[Win64]Lump reservation of %I64u GB is OK. Address is %p.\n"), mem_size/GIGA, baseadr2); #endif }
まずWindowsXP SP2で試してみます。
D:\>largemem [Win32]Available virtual address space is 2041 MB. [Win32]Lump reservation of 1987 MB is OK. Address is 00480000. D:\>
次に、x64版WindowsXP(Ver.1218, Build 3790)で試してみます。(64ビットの方は完了するまで時間がかかります。)
D:\>largemem [Win32]Available virtual address space is 2036 MB. [Win32]Lump reservation of 1910 MB is OK. Address is 005B0000. D:\>
D:\>largemem [Win64]Available virtual address space is 8191 GB. [Win64]Lump reservation of 1901 GB is OK. Address is 000000007FFF0000. D:\>
32ビットの方はどちらも2GB弱確保できています。64ビットの方は一括では8TB弱確保できず2TB弱しか確保できていませんが、それでも32ビットの1000倍弱もあります。本当、広大です。AWEよりもこちらの方がお手軽です。(一括では8TB弱確保できなくても、より小さなサイズで複数回のメモリ確保をすることで、トータル8TB弱のメモリ確保ができるはず。)
■/LARGEADDRESSAWAREを付けて比較
32ビット用をビルドする際、リンカで/LARGEADDRESSAWAREオプションを指定すると、おもしろいことが起こります。
こうやってビルドしたものをまずWindowsXP SP2で実行します。
D:\>largemem [Win32]Available virtual address space is 2041 MB. [Win32]Lump reservation of 1987 MB is OK. Address is 00480000. D:\>
/LARGEADDRESSAWAREオプションなしでビルドしたものと同じ結果です。一応、4GT RAM TuningなWindowsXP SP2(boot.iniに/3GBオプションを付加)でも試してみます。
D:\>largemem [Win32]Available virtual address space is 3065 MB. [Win32]Lump reservation of 1987 MB is OK. Address is 00480000. D:\>
当然ですが、仮想アドレス空間が3GB弱に拡大しています。いよいよ、x64版WindowsXP(Ver.1218, Build 3790)で試してみます。
D:\>largemem [Win32]Available virtual address space is 4084 MB. [Win32]Lump reservation of 2047 MB is OK. Address is 7FFF0000. D:\>
なんと32ビットのプロセスなのに、4GB弱の仮想アドレス空間が使えるようになりました。(一括で確保できるサイズはほぼ2GBきっかりで60MB程度増えただけだが。)それだけではありません。アドレスにもご注目ください。0~4GBの仮想アドレス空間の上位2GB(アドレス(番地)が2GB~4GB)に確保できています。この領域は32-bit版Windowsではシステムが予約している領域で、通常は使えません。
32ビットのアプリケーションも/LARGEADDRESSAWAREオプションをつけてリンクしてWOW64上で実行すれば、64-bit版Windowsのメリットを享受できるわけです。4GT RAM Tuningよりもお手軽かつ広いです。
■仮想アドレス空間の使用状況
ついでなので仮想アドレス空間の使用状況を一覧表示するプログラムを作ります。目的は2つあります。1つ目はアドレス空間のどの辺りに大量の未使用エリア(MEM_FREEなエリア)があるのかを調べること、2つ目はシステムが予約していてアクセスできない領域を調べることです。
#include <windows.h> #include <stdio.h> #include <string.h> #include <tchar.h> void main(void){ LPBYTE baseadr=0x0; MEMORY_BASIC_INFORMATION mbi; TCHAR message[256]; TCHAR bar[32]; _tprintf(TEXT("Address Size(bytes) Status\n")); while(1){ if(VirtualQuery(baseadr, &mbi, sizeof(mbi))) { #ifndef _WIN64 // for Win32 _stprintf(message, TEXT("%p %08lx"), mbi.BaseAddress, mbi.RegionSize); #else // for Win64 _stprintf(message, TEXT("%p %016I64lx"), mbi.BaseAddress, mbi.RegionSize); #endif // if(mbi.State&MEM_FREE){ // MEM_FREE _tcscat(message, TEXT(" MEM_FREE")); } else { // MEM_COMMIT or MEM_RESERVE if(mbi.State&MEM_COMMIT) _tcscat(message, TEXT(" MEM_COMMIT")); if(mbi.State&MEM_RESERVE) _tcscat(message, TEXT(" MEM_RESERVE")); if(mbi.Protect&PAGE_EXECUTE) _tcscat(message, TEXT(" PAGE_EXECUTE")); if(mbi.Protect&PAGE_EXECUTE_READ) _tcscat(message, TEXT(" PAGE_EXECUTE_READ")); if(mbi.Protect&PAGE_EXECUTE_READWRITE) _tcscat(message, TEXT(" PAGE_EXECUTE_READWRITE")); if(mbi.Protect&PAGE_EXECUTE_WRITECOPY) _tcscat(message, TEXT(" PAGE_EXECUTE_WRITECOPY")); if(mbi.Protect&PAGE_NOACCESS) _tcscat(message, TEXT(" PAGE_NOACCESS")); if(mbi.Protect&PAGE_READONLY) _tcscat(message, TEXT(" PAGE_READONLY")); if(mbi.Protect&PAGE_READWRITE) _tcscat(message, TEXT(" PAGE_READWRITE")); if(mbi.Protect&PAGE_WRITECOPY) _tcscat(message, TEXT(" PAGE_WRITECOPY")); if(mbi.Protect&PAGE_GUARD) _tcscat(message, TEXT(" PAGE_GUARD")); if(mbi.Protect&PAGE_NOCACHE) _tcscat(message, TEXT(" PAGE_NOCACHE")); if(mbi.Protect&PAGE_WRITECOMBINE) _tcscat(message, TEXT(" PAGE_WRITECOMBINE")); if(mbi.Type&MEM_IMAGE) _tcscat(message, TEXT(" MEM_IMAGE")); if(mbi.Type&MEM_MAPPED) _tcscat(message, TEXT(" MEM_MAPPED")); if(mbi.Type&MEM_PRIVATE) _tcscat(message, TEXT(" MEM_PRIVATE")); } // END of if() _tcscat(message, TEXT("\n")); _tprintf(message); // baseadr=(LPBYTE)mbi.BaseAddress+mbi.RegionSize; if(baseadr==0x0) break; } else { #ifndef _WIN64 // for Win32 _tcscpy(bar, TEXT("--------")); #else // for Win64 _tcscpy(bar, TEXT("----------------")); #endif _tprintf(TEXT("%p %s Cannot access\n"), baseadr, bar); break; } // END of if() } // END of while() }
32-bit版(/LARGEADDRESSAWAREなし)と64-bit版とを実行します。(仮想アドレス空間の使用状況はプログラムによっても変わってきますし、どのようなDLLがロードされるかによっても変わってきます。下記に示すのは、あくまでも一例です。)
D:\>memview Address Size(bytes) Status 00000000 00010000 MEM_FREE 00010000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00011000 0000f000 MEM_FREE 00020000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00021000 0000f000 MEM_FREE 00030000 000fd000 MEM_RESERVE MEM_PRIVATE 0012D000 00001000 MEM_COMMIT PAGE_READWRITE PAGE_GUARD MEM_PRIVATE 0012E000 00002000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00130000 00003000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00133000 0000d000 MEM_FREE 00140000 00001000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00141000 0000f000 MEM_FREE 00150000 00004000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00154000 000fc000 MEM_RESERVE MEM_PRIVATE 00250000 00006000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00256000 0000a000 MEM_RESERVE MEM_PRIVATE 00260000 00003000 MEM_COMMIT PAGE_READWRITE MEM_MAPPED 00263000 0000d000 MEM_RESERVE MEM_MAPPED 00270000 00016000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00286000 0000a000 MEM_FREE 00290000 0003d000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 002CD000 00003000 MEM_FREE 002D0000 00041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00311000 0000f000 MEM_FREE 00320000 00006000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00326000 0000a000 MEM_FREE 00330000 00041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00371000 0000f000 MEM_FREE 00380000 00007000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00387000 00009000 MEM_RESERVE MEM_PRIVATE 00390000 00003000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00393000 0006d000 MEM_FREE 00400000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 00401000 00021000 MEM_COMMIT PAGE_EXECUTE_WRITECOPY MEM_IMAGE 00422000 00046000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 00468000 0000e000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 00476000 00006000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 0047C000 7c384000 MEM_FREE 7C800000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C801000 00082000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 7C883000 00003000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 7C886000 00002000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 7C888000 000a9000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C931000 0000f000 MEM_FREE 7C940000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C941000 0007b000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 7C9BC000 00003000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 7C9BF000 00002000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 7C9C1000 0001c000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C9DD000 02d13000 MEM_FREE 7F6F0000 00007000 MEM_COMMIT PAGE_EXECUTE_READ MEM_MAPPED 7F6F7000 000f9000 MEM_RESERVE MEM_MAPPED 7F7F0000 007c0000 MEM_FREE 7FFB0000 0002a000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 7FFDA000 00004000 MEM_FREE 7FFDE000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 7FFDF000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 7FFE0000 00001000 MEM_COMMIT PAGE_READONLY MEM_PRIVATE 7FFE1000 0000f000 MEM_RESERVE PAGE_NOACCESS MEM_PRIVATE 7FFF0000 -------- Cannot access D:\>
D:\>memview Address Size(bytes) Status 0000000000000000 0000000000010000 MEM_FREE 0000000000010000 0000000000001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 0000000000011000 000000000000f000 MEM_FREE 0000000000020000 0000000000001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 0000000000021000 000000000000f000 MEM_FREE 0000000000030000 00000000000fc000 MEM_RESERVE MEM_PRIVATE 000000000012C000 0000000000002000 MEM_COMMIT PAGE_READWRITE PAGE_GUARD MEM_PRIVATE 000000000012E000 0000000000002000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 0000000000130000 0000000000005000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 0000000000135000 000000000000b000 MEM_FREE 0000000000140000 0000000000006000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 0000000000146000 00000000000fa000 MEM_RESERVE MEM_PRIVATE 0000000000240000 0000000000004000 MEM_COMMIT PAGE_READWRITE MEM_MAPPED 0000000000244000 000000000000c000 MEM_RESERVE MEM_MAPPED 0000000000250000 0000000000016000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 0000000000266000 000000000000a000 MEM_FREE 0000000000270000 0000000000034000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00000000002A4000 000000000000c000 MEM_FREE 00000000002B0000 0000000000041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00000000002F1000 000000000000f000 MEM_FREE 0000000000300000 0000000000006000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 0000000000306000 000000000000a000 MEM_FREE 0000000000310000 0000000000041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 0000000000351000 000000000000f000 MEM_FREE 0000000000360000 0000000000010000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 0000000000370000 0000000000003000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 0000000000373000 000000000008d000 MEM_FREE 0000000000400000 0000000000001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 0000000000401000 000000000000a000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 000000000040B000 0000000000003000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 000000000040E000 0000000000004000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 0000000000412000 0000000000001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 0000000000413000 000000000000d000 MEM_FREE 0000000000420000 0000000000027000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 0000000000447000 00000000000d9000 MEM_RESERVE MEM_PRIVATE 0000000000520000 00000000777c0000 MEM_FREE 0000000077CE0000 0000000000001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 0000000077CE1000 00000000000e4000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 0000000077DC5000 0000000000004000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 0000000077DC9000 0000000000001000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 0000000077DCA000 00000000000c8000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 0000000077E92000 000000000000e000 MEM_FREE 0000000077EA0000 0000000000001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 0000000077EA1000 00000000000e3000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 0000000077F84000 0000000000006000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 0000000077F8A000 0000000000002000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 0000000077F8C000 0000000000067000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 0000000077FF3000 0000000006fed000 MEM_FREE 000000007EFE0000 0000000000009000 MEM_COMMIT PAGE_EXECUTE_READ MEM_MAPPED 000000007EFE9000 00000000000f7000 MEM_RESERVE MEM_MAPPED 000000007F0E0000 0000000000f00000 MEM_RESERVE MEM_PRIVATE 000000007FFE0000 0000000000001000 MEM_COMMIT PAGE_READONLY MEM_PRIVATE 000000007FFE1000 000000000000f000 MEM_RESERVE MEM_PRIVATE 000000007FFF0000 000007ff7ffc0000 MEM_FREE 000007FFFFFB0000 000000000002a000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 000007FFFFFDA000 0000000000003000 MEM_FREE 000007FFFFFDD000 0000000000002000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 000007FFFFFDF000 0000000000001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 000007FFFFFE0000 0000000000010000 MEM_RESERVE PAGE_NOACCESS MEM_PRIVATE 000007FFFFFF0000 ---------------- Cannot access D:\>
ハイライト表示になっている箇所にご注目ください。32-bit版では、アドレス0x47C000から0x7c384000byte(1987MB弱)の未使用エリアがあります。さらにアドレス0x7FFF0000(全4GBの仮想アドレス空間のうち上位2GBは0x80000000から始まるので、ちょうどその64KB前になる。)から上位にはアクセスできないこともわかります。64-bit版では、アドレス0x7FFF0000から0x7ff7ffc0000byte(8189GB弱)の未使用エリアがあります。(なぜこのエリアをフルに満たすだけのサイズで確保できなかったのかは不明。)アドレス0x520000から始まるエリアにも0x777c0000byte(1911MB弱)の未使用エリアがあります。アドレス0x7FFFFFF0000(全16TBの仮想アドレス空間のうち上位8TBは0x80000000000から始まるので、ちょうどその64KB前になる。)から上位にはアクセスできないこともわかります。
次に/LARGEADDRESSAWAREオプションを付けてビルドしたもの(32-bit版)を4GT RAM TuningなWindowsXP SP2(boot.iniに/3GBオプションを付加)とx64版WindowsXP(WOW64)上で実行します。
D:\>memview Address Size(bytes) Status 00000000 00010000 MEM_FREE 00010000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00011000 0000f000 MEM_FREE 00020000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00021000 0000f000 MEM_FREE 00030000 000fd000 MEM_RESERVE MEM_PRIVATE 0012D000 00001000 MEM_COMMIT PAGE_READWRITE PAGE_GUARD MEM_PRIVATE 0012E000 00002000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00130000 00003000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00133000 0000d000 MEM_FREE 00140000 00001000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00141000 0000f000 MEM_FREE 00150000 00004000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00154000 000fc000 MEM_RESERVE MEM_PRIVATE 00250000 00006000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00256000 0000a000 MEM_RESERVE MEM_PRIVATE 00260000 00003000 MEM_COMMIT PAGE_READWRITE MEM_MAPPED 00263000 0000d000 MEM_RESERVE MEM_MAPPED 00270000 00016000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00286000 0000a000 MEM_FREE 00290000 0003d000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 002CD000 00003000 MEM_FREE 002D0000 00041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00311000 0000f000 MEM_FREE 00320000 00006000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00326000 0000a000 MEM_FREE 00330000 00041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00371000 0000f000 MEM_FREE 00380000 00007000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00387000 00009000 MEM_RESERVE MEM_PRIVATE 00390000 00003000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00393000 0006d000 MEM_FREE 00400000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 00401000 00021000 MEM_COMMIT PAGE_EXECUTE_WRITECOPY MEM_IMAGE 00422000 00046000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 00468000 0000e000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 00476000 00006000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 0047C000 7c384000 MEM_FREE 7C800000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C801000 00082000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 7C883000 00003000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 7C886000 00002000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 7C888000 000a9000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C931000 0000f000 MEM_FREE 7C940000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C941000 0007b000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 7C9BC000 00003000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 7C9BF000 00002000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 7C9C1000 0001c000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7C9DD000 02d13000 MEM_FREE 7F6F0000 00007000 MEM_COMMIT PAGE_EXECUTE_READ MEM_MAPPED 7F6F7000 000f9000 MEM_RESERVE MEM_MAPPED 7F7F0000 007f0000 MEM_FREE 7FFE0000 00001000 MEM_COMMIT PAGE_READONLY MEM_PRIVATE 7FFE1000 3ffcf000 MEM_FREE BFFB0000 0002a000 MEM_COMMIT PAGE_READONLY MEM_MAPPED BFFDA000 00004000 MEM_FREE BFFDE000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE BFFDF000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE BFFE0000 00010000 MEM_RESERVE PAGE_NOACCESS MEM_PRIVATE BFFF0000 -------- Cannot access D:\>
D:\>memview Address Size(bytes) Status 00000000 00010000 MEM_FREE 00010000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00011000 0000f000 MEM_FREE 00020000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00021000 0000f000 MEM_FREE 00030000 000fb000 MEM_RESERVE MEM_PRIVATE 0012B000 00002000 MEM_COMMIT PAGE_READWRITE PAGE_GUARD MEM_PRIVATE 0012D000 00003000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00130000 00006000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00136000 0000a000 MEM_FREE 00140000 00005000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00145000 0007b000 MEM_RESERVE MEM_PRIVATE 001C0000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 001C1000 0000f000 MEM_FREE 001D0000 000fd000 MEM_RESERVE MEM_PRIVATE 002CD000 00001000 MEM_COMMIT PAGE_READWRITE PAGE_GUARD MEM_PRIVATE 002CE000 00002000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 002D0000 00004000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 002D4000 000fc000 MEM_RESERVE MEM_PRIVATE 003D0000 00004000 MEM_COMMIT PAGE_READWRITE MEM_MAPPED 003D4000 0000c000 MEM_RESERVE MEM_MAPPED 003E0000 00016000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 003F6000 0000a000 MEM_FREE 00400000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 00401000 00021000 MEM_COMMIT PAGE_EXECUTE_WRITECOPY MEM_IMAGE 00422000 00046000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 00468000 0000e000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 00476000 00006000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 0047C000 00004000 MEM_FREE 00480000 00034000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 004B4000 0000c000 MEM_FREE 004C0000 00041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00501000 0000f000 MEM_FREE 00510000 00006000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00516000 0000a000 MEM_FREE 00520000 00041000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00561000 0000f000 MEM_FREE 00570000 00007000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE 00577000 00009000 MEM_RESERVE MEM_PRIVATE 00580000 00003000 MEM_COMMIT PAGE_READONLY MEM_MAPPED 00583000 7758d000 MEM_FREE 77B10000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77B11000 00004000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 77B15000 00001000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 77B16000 00003000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77B19000 00007000 MEM_FREE 77B20000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77B21000 0003c000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 77B5D000 00001000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 77B5E000 00005000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 77B63000 00006000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77B69000 00007000 MEM_FREE 77B70000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77B71000 00031000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 77BA2000 00009000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 77BAB000 00001000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 77BAC000 00001000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 77BAD000 00001000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 77BAE000 00001000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 77BAF000 00001000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 77BB0000 00001000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 77BB1000 00005000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77BB6000 0000a000 MEM_FREE 77BC0000 0010f000 MEM_RESERVE MEM_PRIVATE 77CCF000 00011000 MEM_FREE 77CE0000 001b2000 MEM_RESERVE MEM_PRIVATE 77E92000 0000e000 MEM_FREE 77EA0000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77EA1000 000e3000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 77F84000 00006000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 77F8A000 00002000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 77F8C000 00067000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 77FF3000 054dd000 MEM_FREE 7D4D0000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7D4D1000 0000f000 MEM_RESERVE MEM_IMAGE 7D4E0000 00083000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 7D563000 0000d000 MEM_RESERVE MEM_IMAGE 7D570000 00003000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 7D573000 00002000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 7D575000 0000b000 MEM_RESERVE MEM_IMAGE 7D580000 00047000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7D5C7000 00009000 MEM_RESERVE MEM_IMAGE 7D5D0000 00010000 MEM_FREE 7D5E0000 00001000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7D5E1000 0000f000 MEM_RESERVE MEM_IMAGE 7D5F0000 00085000 MEM_COMMIT PAGE_EXECUTE_READ MEM_IMAGE 7D675000 0000b000 MEM_RESERVE MEM_IMAGE 7D680000 00004000 MEM_COMMIT PAGE_READWRITE MEM_IMAGE 7D684000 00001000 MEM_COMMIT PAGE_WRITECOPY MEM_IMAGE 7D685000 0000b000 MEM_RESERVE MEM_IMAGE 7D690000 00049000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7D6D9000 00007000 MEM_RESERVE MEM_IMAGE 7D6E0000 00004000 MEM_COMMIT PAGE_READONLY MEM_IMAGE 7D6E4000 0000c000 MEM_RESERVE MEM_IMAGE 7D6F0000 018f0000 MEM_FREE 7EFE0000 00009000 MEM_COMMIT PAGE_EXECUTE_READ MEM_MAPPED 7EFE9000 000f7000 MEM_RESERVE MEM_MAPPED 7F0E0000 00f00000 MEM_RESERVE MEM_PRIVATE 7FFE0000 00001000 MEM_COMMIT PAGE_READONLY MEM_PRIVATE 7FFE1000 0000f000 MEM_RESERVE MEM_PRIVATE 7FFF0000 7ffc0000 MEM_FREE FFFB0000 0002a000 MEM_COMMIT PAGE_READONLY MEM_MAPPED FFFDA000 00001000 MEM_FREE FFFDB000 00003000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE FFFDE000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE FFFDF000 00001000 MEM_COMMIT PAGE_READWRITE MEM_PRIVATE FFFE0000 00010000 MEM_RESERVE PAGE_NOACCESS MEM_PRIVATE FFFF0000 -------- Cannot access D:\>
/3GBの方では、アドレス0x47C000から0x7c384000byte(1987MB弱)の未使用エリアがあります。アドレス0x7FFE1000から始まるエリアにも0x3ffcf000byte(1023MB弱)の未使用エリアがあります。アクセスできないエリアがアドレス0xBFFF0000(全4GBの仮想アドレス空間のうち上位1GBは0xC0000000から始まるので、ちょうどその64KB前になる。)からになっています。通常よりも1GB広くなっていることがわかります。
WOW64の方では、アドレス0x7FFF0000から0x7ffc0000byte(2047MB弱)の未使用エリアがあります。アドレス0x583000から始まるエリアにも0x7758d000byte(1909MB弱)の未使用エリアがあります。アクセスできないエリアがアドレス0xFFFF0000から始まる最上位64KBだけ、要するに全4GBの仮想アドレス空間をほとんどまるごと使えることがわかります。
起草日:2005年1月8日(土)(www.marbacka.net内の別のサイトで公開)
最終更新日:2017年2月19日(日)