2012-09-24 1 views
10

나는 연속 레이아웃이 여러 구조체가 : , 위의 구조체 유형에 대한 Marshal.SizeOf를 호출Marshal.SizeOf은 추가 바이트를 제공

struct S1 
{ 
    Guid id; 
} 

struct S2 
{ 
    Guid id; 
    short s; 
} 

struct S3 
{ 
    Guid id; 
    short s; 
    short t; 
} 

를 내가 가지고 :

Size: 
S1 = 16, as expected. 
S2 = 20, copied an instance to a byte array, it only occupies first 18 bytes. 
S3 = 20. 

내 질문을 그 이유는 S2의 크기가 20이지만 18이 아닌 이유입니다. 그리고이 문제는 Guid이 구조체에있을 때만 나타납니다.

죄송합니다. msdn에서 유용한 정보를 찾을 수 없습니다. 나는 Marshal.SizeOf이 메모리에서 차지할 공간의 크기를 알려주지 만 크기를 4의 배수로 만들려면 2 여분의 바이트가 필요한 이유를 알고 싶습니다.

그리고이 "문제"를 어떻게 피할 수 있습니까?

고맙습니다.

+0

@Hans Passant의 구조 메모리 레이아웃에 대한 매우 철저한 [답] (http://stackoverflow.com/a/3362736/1289454)을보십시오. Marhsal.SizeOf는 단지 추측 할 수 있다고 주장한다. – gowansg

답변

9

구조체에 내포 된 [StructLayout] 때문에 필드가 중요합니다. 마샬링 된 후 구조의 멤버가 정렬되는 방법을 지정합니다. Pack의 기본값은 8입니다. 이는 8 바이트 이하의 모든 멤버가 정렬된다는 것을 나타냅니다. 즉, short는 2의 배수, 4의 int, 4의 long 또는 double의 오프셋에 정렬됩니다.

요점은 배열 배열이 만들어 질 때 계속 정렬되어야한다는 것입니다 . 쉽게 간단한 예로 증명 :

using System; 
using System.Runtime.InteropServices; 

class Program { 
    static void Main(string[] args) { 
     Console.WriteLine(Marshal.SizeOf(typeof(Example))); 
     Console.ReadLine(); 
    } 
} 
struct Example { 
    public int a; 
    public short b; 
} 

출력 : 8

a 부재는 두 개의 여분의 패딩 바이트는 INT 여전히 오프셋에 정렬되도록 구성에 추가 증가 될 수있는 크기를 강제 구조체가 배열에서 사용될 때 4의 배수입니다. 사용자는 속성을 적용하여 결과를 변경할 수

[StructLayout(LayoutKind.Sequential, Pack = 2)] 
struct Example { 
    public int a; 
    public short b; 
} 

출력 : 6

a 부재 이제 구조체가 어레이에서 사용되는 경우가 잘못 정렬 될 것이다.

Guid로 돌아 가면 선언문에서 볼 수 없지만 내부적으로는 여러 멤버로 구성되어 있습니다. 첫 번째 필드는 _a이라는 private 필드이며 int입니다.그러므로 Guid는 4 바이트 정렬이 필요합니다. 따라서 구조체가 배열에서 사용될 때 제대로 정렬되도록하려면 2 개의 여분의 패딩 바이트가 필요합니다. 18 바이트를 얻으려면 S2에 Pack = 1 또는 Pack = 2가 필요합니다.

구조체에 대한 자세한 배경과 .NET에서 처리되는 특별한 방법은 this answer입니다.

+0

고맙습니다. – user1695516

0

나는 일부 항목은 4 바이트 (또는 8 바이트) 경계에 메모리에 정렬되어야합니다 때문입니다 생각합니다. 따라서 struct는이 크기의 배수로 만들어져 구조체의 배열이 모두 올바르게 정렬됩니다. 문자열을 포함하는 64 비트 시스템에서는 8 바이트의 배수가됩니다. GUID는 64 비트에서도 4 바이트의 배수만 필요합니다. GUID를 포함하는 구조체가 4 바이트의 배수가 아닌 경우 일부 GUID는이 구조체의 배열에서 4 바이트 경계에 있지 않습니다. '문제'를 피할 수 있다고 생각지 않습니다. 왜 문제입니까?

관련 문제