일반 참조형의 기본 메모리 소비는 얼마나 될까요?
지난번 글을 통해서, 배열과 관련된 인스턴스의 메모리를 살펴보는 방법을 알아봤습니다.
.NET Array는 왜 12bytes의 기본 메모리를 점유할까?
; https://www.sysnet.pe.kr/2/0/1173
배열은 12bytes가 기본소비되는 데요. 그렇다면 일반적인 클래스의 경우에는 얼마나 메모리를 소비할까요?
처음 이 의문이 들었을 때, 저는 간단하게 8bytes라고 생각했습니다. 왜냐하면, ^^ 배열과 비교해서 '요소 수'로 할당된 4bytes가 없어지기 때문입니다. 그런데... 그게 아니더군요. ^^
직접 확인을 해볼까요? 예제를 위해, 코드는 다음과 같이 작성하고,
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program pg = new Program();
Thread.Sleep(-1);
}
}
}
windbg로 확인하면,
0:004> .loadby sos clr
0:004> !name2ee ConsoleApplication1!ConsoleApplication1.Program
PDB symbol for clr.dll not loaded
Module: 00292e9c
Assembly: ConsoleApplication1.exe
Token: 02000002
MethodTable: 00293810
EEClass: 00291424
Name: ConsoleApplication1.Program
0:004> !dumpheap -mt 00293810
Address MT Size
026cbf90 00293810 12
total 0 objects
Statistics:
MT Count TotalSize Class Name
00293810 1 12 ConsoleApplication1.Program
Total 1 objects
0:004> !do 026cbf90
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\syswow64\KERNEL32.dll -
Name: ConsoleApplication1.Program
MethodTable: 00293810
EEClass: 00291424
Size: 12(0xc) bytes
File: D:\...\ConsoleApplication1.exe
Fields:
None
0:004> !dumpclass 00291424
Class Name: ConsoleApplication1.Program
mdToken: 02000002
File: D:\...\ConsoleApplication1.exe
Parent Class: 72cb3ef8
Module: 00292e9c
Method Table: 00293810
Vtable Slots: 4
Total Method Slots: 5
Class Attributes: 100000
Transparency: Critical
NumInstanceFields: 0
NumStaticFields: 0
0:004> dd 026cbf90
026cbf90 00293810 00000000 00000000 00000000
026cbfa0 00000000 00000000 00000000 00000000
보시는 바와 같이, 배열 타입과 동일하게 12bytes를 소비하고 있습니다. 왜냐하면 빈 객체라고 해도 데이터 공간으로 기본 4바이트를 점유하고 있기 때문입니다. (참고로, 00293810 데이터 앞의 4바이트 위치에는 OBJECT HEADER가 위치하고 있습니다.)
혹시나 싶어서, int (4바이트) 형의 필드를 ConsoleApplication1.Program에 선언하고,
namespace ConsoleApplication1
{
class Program
{
int test = 0xFF;
static void Main(string[] args)
{
Program pg = new Program();
Thread.Sleep(-1);
}
}
}
다시 메모리 값을 확인해 보면 다음과 같이 나옵니다.
0:004> !dumpheap -mt [Program 타입의 MT 값]
Address MT Size
024cbf90 0019381c 12
total 0 objects
Statistics:
MT Count TotalSize Class Name
0019381c 1 12 ConsoleApplication1.Program
Total 1 objects
0:004> !dumpmt 0019381c
EEClass: 00191428
Module: 00192e9c
Name: ConsoleApplication1.Program
mdToken: 02000002
File: D:\...\ConsoleApplication1.exe
BaseSize: 0xc
ComponentSize: 0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
0:004> !dumpclass 00191428
Class Name: ConsoleApplication1.Program
mdToken: 02000002
File: D:\...\ConsoleApplication1.exe
Parent Class: 72cb3ef8
Module: 00192e9c
Method Table: 0019381c
Vtable Slots: 4
Total Method Slots: 5
Class Attributes: 100000
Transparency: Critical
NumInstanceFields: 1
NumStaticFields: 0
MT Field Offset Type VT Attr Value Name
72fd28f8 4000001 4 System.Int32 1 instance test
0:004> dd 024cbf90
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\syswow64\KERNEL32.dll -
024cbf90 0019381c 000000ff 00000000 00000000
024cbfa0 00000000 00000000 00000000 00000000
필드를 하나 더 포함하고 있는데도 여전히 12bytes가 소비되고 있습니다. 왜냐하면 필드를 포함하지 않았을 때도 00000000으로 기본 포함되어 있던 영역이 사용되고 있기 때문입니다. 물론 필드 하나를 더 추가하는 순간부터 메모리가 4bytes씩 늘어납니다.
이로써, 그 동안의 이야기를 정리해 보면 아래와 같습니다.
[x86 기준]
0 크기 배열: 12bytes
배열이 아닌 일반 참조형 개체: 12bytes
[x64 기준]
0 크기 배열: 24bytes
배열이 아닌 일반 참조형 개체: 24bytes
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]