2016-05-06 21 views
2

我有非託管結構:如何正確Marshal在C#中的非託管數組沒有不安全

typedef struct 
{ 
    char a[48]; 
    BYTE b; 
    BYTE c; 
    BYTE d;    
    BYTE e;    
    BYTE f; 
    BYTE x; 
    char y[32]; 
    char z[128][32]; 
    }SOMELIKE_STRUCT 

我試圖封送它,因爲它是寫在另一個線程的StackOverflow:

[StructLayout(LayoutKind.Explicit, Pack = 1)] 
    public struct SOMELIKE_STRUCT 
    { 
     [FieldOffset(0)] 
     [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 48)] 
     public byte[] a; 
     [FieldOffset(48)] 
     public byte b; 
     [FieldOffset(49)] 
     public byte c; 
     [FieldOffset(50)] 
     public byte d; 
     [FieldOffset(51)] 
     public byte e; 
     [FieldOffset(52)] 
     public byte f; 
     [FieldOffset(53)] 
     public byte x; 
     [FieldOffset(54)] 
     [MarshalAs(UnmanagedType.ByValArray, ArraySubType=UnmanagedType.U1, SizeConst = 32)] 
     public byte[] y; 
     [FieldOffset(86)] 
     [MarshalAs(UnmanagedType.ByValArray, ArraySubType=UnmanagedType.Struct, SizeConst = 128)] 
     public STRUCT[] z; 
    } 

[StructLayout(LayoutKind.Explicit, Pack = 1)] 
    public struct STRUCT 
    { 
     [FieldOffset(0)] 
     [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 32)] 
     public byte[] name; 
    } 

我有例外:

System.TypeLoadException未處理 附加信息:無法從程序集中加載類型'SOMELIKE_STRUCT''ConsoleApplication2,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null',因爲 它包含一個位於偏移量'54'的對象字段,該對象字段被非對象字段錯誤地對齊或重疊 。

  1. 異常示出當創建這個結構與新:)

    SOMELIKE_STRUCT升=新SOMELIKE_STRUCT(;

  2. 異常顯示當我將創建類(當踏入構造函數)使用結構(之前創建結構的實例)

+1

託管數組對象引用必須對齊以提供內存模型保證更新此類引用始終是原子的。如果[FieldOffset]值正確,則必須用'fixed'關鍵字聲明數組以避免此異常。 –

回答

1

包含在struct中的結構和表格必須放置在地址爲字的多個字節(x86/x64的4/8字節)中。

2

不能完全弄清楚是怎麼回事作爲您的定義似乎正確。

更改佈局順序和刪除手工字段偏移似乎工作:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct SOMELIKE_STRUCT 
{ 
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 48)] 
    public byte[] a; 
    public byte b; 
    public byte c; 
    public byte d; 
    public byte e; 
    public byte f; 
    public byte x; 
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 32)] 
    public byte[] y; 
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 128)] 
    public STRUCT[] z; 
} 

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct STRUCT 
{ 
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 32)] 
    public byte[] name; 
} 

檢查與Marshal.SizeOf大小給予4182個字節,並與Marshal.OffsetOf檢查得到的佈局給出了同樣的偏移量爲在原始碼。我相信這裏有人可以詳細說明爲什麼會發生這種情況。

相關問題