windbg - 닷넷 메모리 덤프에서 정적(static) 필드 값을 조사하는 방법
지난번에, singleton을 비롯해 인스턴스화된 객체 값을 조사하는 방법을 설명했는데요.
windbg - 닷넷 메모리 덤프에서 전역 객체의 내용을 조사하는 방법
; https://www.sysnet.pe.kr/2/0/11460
간단하게 다음과 같은 예제 코드를 이용해 테스트할 수 있습니다.
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
InstanceClass inst = new InstanceClass();
inst.Count++;
Console.WriteLine(inst.Count);
Console.ReadLine(); // 이 시점에 메모리 덤프
}
}
public class InstanceClass
{
public int Count;
}
}
덤프 파일을 windbg에서 열고
지난번 글에서 설명한 대로 InstanceClass 타입의 Count 값을 이렇게 확인하게 됩니다.
0:000> !dumpheap -type ConsoleApp1.InstanceClass
Address MT Size
0000013d93f26ce8 00007ffde3015ab8 24
Statistics:
MT Count TotalSize Class Name
00007ffde3015ab8 1 24 ConsoleApp1.InstanceClass
Total 1 objects
0:000> !DumpObj /d 0000013d93f26ce8
Name: ConsoleApp1.InstanceClass
MethodTable: 00007ffde3015ab8
EEClass: 00007ffde3161020
Size: 24(0x18) bytes
File: E:\ConsoleApp1\ConsoleApp1\bin\Debug\ConsoleApp1.exe
Fields:
MT Field Offset Type VT Attr Value Name
00007ffe3df69500 4000002 8 System.Int32 1 instance 1 Count
그럼, 이제 위의 예제 코드에 static 필드를 가진 타입을 추가해 보겠습니다.
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
StaticClass.Count++;
Console.WriteLine(StaticClass.Count);
InstanceClass inst = new InstanceClass();
inst.Count++;
Console.WriteLine(inst.Count);
Console.ReadLine();
}
}
public class StaticClass
{
public static int Count;
}
public class InstanceClass
{
public int Count;
}
}
당연하겠지만, StaticClass 클래스의 Count 값은 dumpheap으로는 알 수 없습니다. 심지어, 위의 경우에는 인스턴스화 한 적도 없기 때문에 dumpheap으로는 기록조차 찾을 수 없습니다.
0:000> !dumpheap -type ConsoleApp1.StaticClass
Address MT Size
Statistics:
MT Count TotalSize Class Name
Total 0 objects
new를 했어야 Managed Heap에 기록이 남기 때문에 위의 결과는 지극히 정상적인 것입니다. 대신, static 필드의 값은 클래스 정보를 통해 알아낼 수 있습니다. 이를 위해 다음과 같이 클래스의 식별자를 알아내고,
0:000> !name2ee ConsoleApp1.exe!ConsoleApp1.StaticClass
Module: 00007ffde3014110
Assembly: ConsoleApp1.exe
Token: 0000000002000003
MethodTable: 00007ffde3015b68
EEClass: 00007ffde3161098
Name: ConsoleApp1.StaticClass
그에 대해 DumpClass 명령을 내리면 됩니다.
0:000> !DumpClass /d 00007ffde3161098
Class Name: ConsoleApp1.StaticClass
mdToken: 0000000002000003
File: E:\ConsoleApp1\ConsoleApp1\bin\Debug\ConsoleApp1.exe
Parent Class: 00007ffe3d8d1968
Module: 00007ffde3014110
Method Table: 00007ffde3015b68
Vtable Slots: 4
Total Method Slots: 5
Class Attributes: 100001
Transparency: Critical
NumInstanceFields: 0
NumStaticFields: 1
MT Field Offset Type VT Attr Value Name
00007ffe3df69500 4000001 3c System.Int32 1 static 1 Count
참고로, 타입 이름을 기준으로 하는 "!dumpheap -type ConsoleApp1.InstanceClass" 명령어로 관리 힙을 검색하는 것은 경우에 따라 불편함이 있습니다. 왜냐하면, 검색어로 준 "ConsoleApp1.InstanceClass" 이름과 정확히 일치하는 것이 아니라 그것을 포함하고 있어도 검색이 되기 때문입니다.
따라서, 해당 타입에 대해 정확히 일치하는 것만 검색하고 싶다면 name2ee 명령을 통해 우선 그 타입의 MethodTable을 얻는 것이 좋습니다.
0:017> !name2ee *!ConsoleApp1.InstanceClass
Module: 02d32010 (teslib.dll)
Token: 0x02000154
MethodTable: 043117dc
EEClass: 02db3280
Name: ConsoleApp1.InstanceClass
이렇게 알아낸 MethodTable로 dumpheap 검색을 하면 됩니다.
0:017> !DumpHeap -mt 043117dc
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]