2016-06-27 2 views
2

WinDbg를 사용하여 .NET 프로세스의 메모리 덤프를 분석 중이며 힙에있는 모든 System.Int32 변수의 크기가 24 바이트으로보고되었음을 확인했습니다. 여기에 변수 중 하나에 해당 DumpObj 호출의 예 : WinDbg에서 System.Int32 변수를 24 바이트로 표시하는 이유는 무엇입니까?

0:000> !DumpObj /d 00000061c81c0e80 
Name:  System.Int32 
MethodTable: 00007fff433f37c8 
EEClass:  00007fff42e30130 
Size:  24(0x18) bytes 
File:  C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 
Fields: 
       MT Field Offset     Type VT  Attr   Value Name 
00007fff433f37c8 4000456  8   System.Int32 1 instance    141 m_value 

는 지금까지 내가 아는 한, 크기 선택 System.Int32 4 바이트로되어있다. 이 불일치의 원인은 무엇입니까?

+4

일반적인 Skeet이 이에 대한 블로그 게시물을 작성했습니다. 64 비트에서 24 바이트는 "최소 크기"입니다. –

+1

[여기] (https://codeblog.jonskeet.uk/2011/04/05/of-memory-and-strings/)는 해당 게시물입니다 (참조 용). –

+1

힙에있는 경우 boxed입니다. 즉 일반적인 객체 오버 헤드 (x86에서는 객체 당 8 바이트, x64에서는 객체 당 16 바이트)가 있고 4/8 바이트 경계에 정렬해야하므로 12B x86에서 24B, x64에서 24B. – Groo

답변

3

. 32 비트 MS.NET 런타임에서 이것은 8 바이트이며 64 비트, 16 바이트 (고지 사항 : 이것은 계약 적으로 체결 된 것이 아니며 나중에 또는 .NET 런타임의 준수 구현에서 변경 될 수 있습니다. .

int에는 박스가 있으므로 16 바이트 오버 헤드가 발생합니다. 따라서 총 20 바이트를 사용할 것으로 예상 할 수 있습니다. 음, 64 비트 시스템을 제외하고는 객체와 구조체가 8 바이트 경계로 채워져 있기 때문에 실제로는 int 당 24 바이트가됩니다.

반대로 struct을 16 개의 정수로 사용하면 16 + 4 * 16 = 80 바이트의 메모리 만 사용하여 정수 당 총 5 바이트를 사용하게됩니다.

또한이 대부분은 구현 세부 사항이므로 신뢰할 수있는 것은 아닙니다. 하나의 유효한 .NET 런타임이 1 MiB의 메모리에 하나의 int을 저장하는 것은 완벽하게 가능하며 모든 계약상의 행동을 준수하는 한 간결한 표현이나 인터 네킹으로 저장할 수도 있습니다 유형의. 실제 MS 런타임 구현과 비교해도 상당히 단순합니다. 예를 들어, 객체가 충분히 커지면 오버 헤드가 더 많이 필요합니다.

+0

실제로 배열은 다소 다릅니다. 'int' 배열은 x64에서'28 + length * 4'를 취합니다. – Groo

+0

@Groo 그래, 내가 그걸 게시 한 후 두 번째 깨달았다 :) 당신은 또한 길이와 순위와 뭐든 필요 : D 조 – Luaan

2

그것은 INT32의 크기가 아닌 DD 또는 DQ 주소를하고 참조하여 INT32 두 번째 DWORD에 갇혀 또는 12 바이트 각각 86/64

0:004> .shell -ci "!DumpObj /d 01c72360" grep -i size 
    Size:  12(0xc) bytes 
    .shell: Process exited 
    0:004> dd 01c72360 l4 
    01c72360 5890c770 000001b5 80000000 5890afb0 
    0:004> .shell -ci "!DumpObj /d 01c72360" grep -i method 
    MethodTable: 5890c770 
    .shell: Process exited 
    0:004> .shell -ci "!DumpObj /d 01c72360" grep -i value 
      MT Field Offset     Type VT  Attr Value Name 
    5890c770 400044f  4   System.Int32 1 instance  437 m_value 
    .shell: Process exited 
    0:004> ? 1b5 
    Evaluate expression: 437 = 000001b5 
에 대한 개체 당 24 바이트의 암시 오버 헤드가
QWORD INT32 떠나 는

떨어져 86 년 dumpobj

actualsizereqdfor(L"stream\0") = 7 * sizeof(wchar_t) == 7 * 2 == 0n14;  
sizeof(method table)           == 0n04; 
sizeof(sizeof(L"stream))          == 0n04;  
sizeof(padding ?? terminator ?? whatever ??)     == 0n04; 
so total size             == 0n26 

결과를 WideString이 "스트림"을 해부 할 수 있습니다 143,210

힙에있는 모든 객체에 대한 오버 헤드가있어 원료 표시

0:004> db 01c73ad0 l1a 
01c73ad0 b0 af 90 58 06 00 00 00-73 00 74 00 72 00 65 00 ...X....s.t.r.e. 
01c73ae0 61 00 6d 00 00 00 00 00-00 00     a.m.......