http://byung.egloos.com/4521186
Windows 32bit System 하에서 하나의 Process는 대략 2GB(~7fffffff address) Virtual Address 영역을 사용한다. 이는 사용자 모드에서 사용 가능한 가상메모리이며, 커널모드에서는 2GB를 따로 사용한다. (물론, 3gb option을 사용하면, bfffffff 까지 User mode에서 사용가능하고, 나머지 1GB는 kernel이 사용한다. Win32가 2^32 arrange 를 갖는 다고 생각하면, 하나의 Process가 사용할 수 있는 Virtual Address layout는 4GB이며, 이를 Kernel과 User mode에서 나눠 갖는 다고 생각하면 된다.) 이는 Physical Memory와 관련 없이 하나의 Process가 사용하는 가상메모리영역이다. 그러므로, Win32 System의 Windows 하에서 실행하는 임의의 User Mode Application이 2GB에 이르기까지 메모리를 사용하고 있다면, 메모리부족오류가 발생할 수 있다.
해당 Application이 메모리관련오류, 특히 메모리누수와 같은 문제를 갖고 있다면, Process가 사용하는 Memory 상태를 확인하는 것은 중요하다. 여기서 메모리의 상태라는 것은 reserve, committed 그리고, Free 를 말한다. Virtual Memory는 성능 및 여러 가지 이유로 임의의 영역을 reserve 하고 나서 실제 사용시에 commit 한다. 물론, 다 사용하고 나면 free 시킬 수 있다. 임의의 Process 에 Windbg를 Attach 하여 !vadump –v command를 실행하면, 연속된 가상메모리의 상태를 다음과 같이 확인할 수 있다.
BaseAddress: 533f0000
AllocationBase: 533f0000
AllocationProtect: 00000004 PAGE_READWRITE
RegionSize: 00001000
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
BaseAddress: 533f1000
AllocationBase: 00000000
RegionSize: 0000f000
State: 00010000 MEM_FREE
Protect: 00000001 PAGE_NOACCESS
BaseAddress: 53400000
AllocationBase: 53400000
AllocationProtect: 00000004 PAGE_READWRITE
RegionSize: 00001000
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
BaseAddress: 53401000
AllocationBase: 00000000
RegionSize: 0000f000
State: 00010000 MEM_FREE
Protect: 00000001 PAGE_NOACCESS
BaseAddress: 53410000
AllocationBase: 53410000
AllocationProtect: 00000004 PAGE_READWRITE
RegionSize: 00001000
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
메모리가 상당히 조각화되어 있다면, 해당 log는 상당한 양이 될 수도 있다. 반드시, .logopen 하여 file logging을 하도록 한 후에, 연속된 메모리의 상태를 차근차근히 살펴볼 필요가 있다. (하지만, 굉장히 짜증나는 작업이 될 수도 있다.) 그러면, 규칙적으로 Allocation되어 있는 데이타 Block을 찾거나, 메모리 곳곳에 마치 pinning되어 메모리조각화를 유발하는 메모리 block을 찾을 수도 있게 된다. (dc command를 통해 메모리영역에 Application개발자가 인식 가능한 데이터가 존재하는 지 확인해 볼 수 있으며, dds command를 통해 stack 영역인지 여부를 Check 할 수도 있다.
0:000> dds 533f0000
533f0000 533f0040
533f0004 00001000
533f0008 61447720 msdtcprx!UTLink<CMMPageInfo<CITransaction> *>::`vftable'
533f000c 533f0000
533f0010 53380008
533f0014 53400008
533f0018 00000001
533f001c 6149b778 msdtcprx!g_MemMgrCITransaction+0x20
533f0020 61431910 msdtcprx!UTStaticList<CITransaction *>::`vftable'
…
…
0:000> dds 53400000
53400000 53400040
53400004 00001000
53400008 61447720 msdtcprx!UTLink<CMMPageInfo<CITransaction> *>::`vftable'
5340000c 53400000
53400010 533f0008
53400014 533a0008
53400018 00000001
5340001c 6149b778 msdtcprx!g_MemMgrCITransaction+0x20
53400020 61431910 msdtcprx!UTStaticList<CITransaction *>::`vftable'
…
)
메모리 누수의 경우는 DebugDiag 와 같은 Tool이나, gflag에서 +ust option(create user mode stack database)를 이용한 UMDH.exe 를 이용하는 것이 API level에서 확인할 수 있는 가장 좋은 접근이지만, 이와 같은 접근 전에 전반적으로 메모리의 상태를 보고 이후에 좀 더 구체적으로 메모리 문제에 접근한다는 점에서 Virtual address dump는 유용할 수 있다.