在下面的代码中,我观察到封送器正在读取3字节源数组以填充另外8个字节的数据。随着时间的推移,代码最终会抛出内存访问冲突。有没有办法告诉编组只在将指针转换为结构时编组前3个字节?如果我制作Articulations数组" NonSerialized"然后构造函数在处理11个字节的源数组时会抛出访问冲突。
using System;
using System.Runtime.InteropServices;
namespace MarshallingTest
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Articulation
{
public const int BaseSize = 8;
public byte attribute1;
public byte attribute2;
public byte attribute3;
public byte attribute4;
public byte attribute5;
public byte attribute6;
public byte attribute7;
public byte attribute8;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestEntity
{
public const int BaseSize = 3;
public byte EntityId; // 1 byte
public byte Variable; // 1 byte
public byte NumArticulations; // 1 byte
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct)]
public Articulation[] Articulations; // 8 bytes each
public TestEntity(byte[] rawData)
{
unsafe
{
fixed (byte* pData = rawData)
{
// I am observing that the marshaler is reading past the 3 bytes
// to populate another 8 bytes of data. With time, the code
// will eventually throw a memory access violation.
//
// Is there a way to tell the marshaller to only marshal the
// first 3 bytes when converting a pointer to a structure?
Marshal.PtrToStructure((IntPtr) pData, this);
for (int i = 0; i < BaseSize + Articulation.BaseSize; i++)
{
Console.WriteLine("pData + " + i + " = " + *(pData + i));
}
}
}
}
public byte[] ToRaw()
{
byte[] byteArray = new byte[BaseSize + Articulation.BaseSize*Articulations.Length];
unsafe
{
fixed (byte* pData = byteArray)
{
Marshal.StructureToPtr(this, (IntPtr) pData, false);
}
}
return byteArray;
}
}
internal class Program
{
private const int TestDataSize = TestEntity.BaseSize;
private static void Main()
{
byte[] testData = new byte[TestDataSize];
for (int i = 0; i < TestDataSize; i++)
{
testData[i] = (byte) (i + 1);
}
TestEntity test = new TestEntity(testData);
// Print resulting array. You'll see that data outside the source
// byte array was marshalled into the test structure.
Console.WriteLine(test.EntityId);
Console.WriteLine(test.Variable);
Console.WriteLine(test.NumArticulations);
Console.WriteLine(test.Articulations[0].attribute1);
Console.WriteLine(test.Articulations[0].attribute2);
Console.WriteLine(test.Articulations[0].attribute3);
Console.WriteLine(test.Articulations[0].attribute4);
Console.WriteLine(test.Articulations[0].attribute5);
Console.WriteLine(test.Articulations[0].attribute6);
Console.WriteLine(test.Articulations[0].attribute7);
Console.WriteLine(test.Articulations[0].attribute8);
Console.WriteLine("Test complete.");
}
}
}