C# Struct의 메모리 레이아웃 문제 해결

3591 단어
질문: 다음 struct의 실례 크기와 메모리 레이아웃을 말씀해 주십시오
 
  
struct Struct1
{
    public byte a;
    public short b;
    public string c;
    public int d;
}

struct Struct2
{
    public byte a;
    public long b;
    public byte c;
    public string d;
}

struct Struct3
{
    byte a;
    byte b;
    long c;
}

struct Struct4
{
    byte a;
    long b;
    byte c;
}


이따가 답을 보고 너의 이해와 큰 차이가 있는지 확인해 볼까?사실 struct와class의 메모리 레이아웃은 모두 Struct Layout Attribute의 구조 매개 변수입니다: Layout Kind 매거진에 의해 결정되고 struct는 컴파일러에 Layout Kind를 추가합니다.Sequential,class는 컴파일러에 Layout Kind를 추가합니다.Auto.Sequential은 실험 데이터를 통해 다음과 같이 요약할 수 있습니다.
1. 인용 형식이 없는 struct: 정의된 순서에 따라 배열하고 메모리 레이아웃은 c, c++ 규칙과 같습니다.예를 들면 다음과 같습니다.
Byte a;
Byte b;
Long c;
의 크기는 a, b는 4 바이트, c는 8 바이트입니다.
Byte a
Long c
Byte b
의 크기는 a 충전 8 바이트, c 충전 8 바이트, b 충전 8 바이트입니다.
2. 인용 형식이 있는 struct: 4바이트 이상의 필드 -> 인용 필드 -> 4바이트 이하의 필드
4바이트 이하의 필드는 크기에 따라 배열되며, 크기가 같으면 정의 순서에 따라 메모리 레이아웃과 규칙 1이 같습니다.그러나 여기서 주의해야 할 점은 필드가 struct 형식이라면 이 필드는 항상 맨 뒤에 있다는 것이다.
그래서 위의 답은:
Struct1:c(4) -> d(4) -> b(2) ->a(2)
Struct2:b(8)-> d(4)-> a(1)c(1) 2바이트 채우기
Struct3: a(1)b(1) 2바이트 채우기-> c(8)
Struct4: a(1) 7바이트 채우기->b(8)->c(1) 7바이트 채우기
직접 실험을 해보고 싶다면 SOS를 사용해야 한다.dll에서 디버깅 (SOS 설정과 입문에 관한 글이 블로그에 많음) 을 진행합니다. struct1을 예로 들면 다음과 같습니다.
Struct1s1 = new Struct1();
s1.a = 1;          
            s1.b = 15;
            s1.c = "c";
            s1.d = 32;
.load sos
확장 C:\WINDOWS\Microsoft가 로드되었습니다.NET\Framework\v2.0.50727\sos.dll
!clrstack -a
PDB symbol for mscorwks.dll not loaded
OS Thread Id: 0x15fc (5628)
ESP       EIP   
0041ee3c 03ba01aa Test_Console.Class12.Main()
    LOCALS:
        0x0041ee84 = 0x01b02b0c
        0x0041ee74 = 0x00000020
        0x0041ee68 = 0x00000000
        0x0041ee50 = 0x00000000
0041f104 6ebd1b4c [GCFrame: 0041f104]
.load sos
확장 C:\WINDOWS\Microsoft가 로드되었습니다.NET\Framework\v2.0.50727\sos.dll
!name2ee *!Test_Console.Struct1//Struct1의 메소드 테이블 주소 가져오기
PDB symbol for mscorwks.dll not loaded
Module: 6d5d1000 (mscorlib.dll)
--------------------------------------
Module: 00192c5c (Test_Console.exe)
Token: 0x02000012
MethodTable: 00193828
EEClass: 007a45b4
Name: Test_Console.Struct1
!clrstack -a//struct1 실례의 창고 주소
OS Thread Id: 0x1438 (5176)
ESP       EIP   
003eef0c 008f00c9 Test_Console.Class12.Main()
    LOCALS:
        0x003eef1c = 0x01c12b0c
003ef17c 6ebd1b4c [GCFrame: 003ef17c]
!dumpvc00193828 0x003eef1c//보기 값 형식의layout
Name: Test_Console.Struct1
MethodTable 00193828
EEClass: 007a45b4
Size: 20(0x14) bytes
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
6d84340c  400001c        a          System.Byte  1 instance        1 a
6d83e910  400001d        8         System.Int16  1 instance       15 b
6d8408ec  400001e        0        System.String  0 instance 01c12b0c c
6d842b38  400001f        4         System.Int32  1 instance       32 d
메모리 창에는 다음과 같은 메모리 레이아웃이 표시됩니다.
0x003EEF1C  01c12b0c 00000020 0001000f
여기에dumpvc를 사용한 후에 하나의 사이즈를 보여 드리겠습니다. 여기는 20바이트입니다. 우리가 계산한 결과보다 8바이트가 더 많습니다. 인용 유형에 추가된 8바이트(syncblkindex+methodtableaddress)가 있기 때문에 여기의 사이즈도 8.

좋은 웹페이지 즐겨찾기