我有我想要在C#編組結構如下:編組字符串(而不是字節數組)的內部結構導致AccessViolationException
- 長度(4個字節)
- 版本(4個字節)
- 機號(16個字節)
我有越來越的MachineID
如在C#string
問題。在結構中,我在頂部指定[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 24)]
,在MachineID
指定[MarshalAs(UnmanagedType.LPStr, SizeConst = 16)]
。但是當我這樣做時,我得到了System.AccessViolationException
被拋出。
如果我將MachineID
更改爲byte[]
並指定[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
它工作正常。
下面是代碼與byte[]
,但不是string
。 ASCII形式的MachineID
是ABCDEFGHIJKLMNO
。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
public class Test
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 24)]
struct Valid
{
public uint Length;
public uint Version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] MachineId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 24)]
struct Invalid
{
public uint Length;
public uint Version;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 16)]
public string MachineId;
}
public static void Main()
{
var bytes = new byte[]
{
0x58, 0, 0, 0,
0, 0, 0, 0,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0
};
var pinnedBuffer = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var ptr = pinnedBuffer.AddrOfPinnedObject();
// Works!
Debug.Assert(bytes.Length == Marshal.SizeOf<Valid>());
var trackerData1 = Marshal.PtrToStructure<Valid>(ptr);
Console.WriteLine("Length: {0}", trackerData1.Length);
Console.WriteLine("Version: {0}", trackerData1.Version);
Console.WriteLine("MachineId: {0}", Encoding.ASCII.GetString(trackerData1.MachineId));
// Doesnt work!
Debug.Assert(bytes.Length == Marshal.SizeOf<Invalid>());
// Throws System.AccessViolationException
var trackerData2 = Marshal.PtrToStructure<Invalid>(ptr);
Console.WriteLine("Length: {0}", trackerData2.Length);
Console.WriteLine("Version: {0}", trackerData2.Version);
Console.WriteLine("MachineId: {0}", trackerData2.MachineId);
pinnedBuffer.Free();
Console.In.ReadLine();
}
}
如果run this code in IDEOne,你會看到它拋出System.AccessViolationException
當它試圖封送string
,它不只是我的電腦。
我很好奇的是爲什麼它的字節數組而不是字符串?