C#/.NET에서 배열을 포함하는 조합을 마샬링하는 이상한 시나리오가 발생했습니다. 다음 프로그램을 고려 :이 프로그램을 실행하면배열로 마샬링 유니온
namespace Marshal
{
class Program
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct InnerType
{
byte Foo;
//[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
//byte[] Bar;
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
struct UnionType
{
[FieldOffset(0)]
InnerType UnionMember1;
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
byte[] UnionMember2;
}
static void Main(string[] args)
{
Console.WriteLine(@"SizeOf UnionType: {0}", System.Runtime.InteropServices.Marshal.SizeOf(typeof(UnionType)));
}
}
}
, 당신은 다음과 같은 예외를 얻을 수 있습니다 :
Could not load type 'UnionType' from assembly 'Marshal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.
을 이제 두 개의 주석 라인의 주석을 해제하는 경우, 프로그램이 잘 실행됩니다. 왜 이런지 궁금하네요. InnerType에 추가 배열을 추가하면 문제가 해결되는 이유는 무엇입니까? 덧붙여 말하자면 배열을 어떤 크기로 만들지는 중요하지 않습니다. 배열이 없으면 UnionMember1과 UnionMember2는 서로 크기가 일치해야합니다. 배열에서는 크기가 일치하지 않지만 예외는 발생하지 않습니다. 다음에 InnerType 변경
업데이트 도 (InnerType에이 시간) 예외를 발생합니다
[StructLayout(LayoutKind.Explicit, Pack = 1)]
struct InnerType
{
[FieldOffset(0)]
byte Foo;
[FieldOffset(1)]
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
byte[] Bar;
}
이 원래의 코드와 동일해야한다는 날 것으로 보인다 (LayoutKind.Sequential
로) 여기서 byte[] Bar
주석 처리되지 않았습니다.
여기서 문제는 단어 경계와 관련이 없다고 생각합니다. 저는 Pack = 1을 사용하고 있습니다. 오히려 예외의 두 번째 부분이라고 생각합니다. "... 오프셋 0은 ... 비 - 객체 필드에 의해 중첩됩니다. " byte []는 참조 유형이고 byte 자체는 값 유형입니다. "byte Foo"가 "byte [] UnionMember2"와 겹쳐지는 것을 볼 수 있습니다. 그러나 이것은 여전히 원래 코드에서 "byte [] bar"의 주석 처리를 제거하면 예외가 사라지는 이유를 설명하지 못합니다.
이 게시물이 도움이 될 것입니다 http://stackoverflow.com/questions/1190079/incorrectly-aligned-or-overlapped-by-a-non-object-field-error, http://stackoverflow.com/questions/ 4673099/c-sharp-un-object-field와 잘못 정렬되거나 겹친 유니온. UnionMember2의 필드 오프셋을 8로 변경하면이 문제가 해결됩니다. –
@David Venegoni - 감사합니다. 나는 이미 이것들을 보았다. # 1190079는 CF 마샬 러에만 적용됩니다. CF를 사용하지 않고 팩을 사용하고 있습니다. # 4673099 해당 사용자의 문제에 대한 해결책이 있지만 예외의 원인을 정확히 설명하지는 않습니다. 오프셋 8을 사용하면 예외 (및 공용체)가 제거되지만 InnerType.bar를 추가하면 예외가 표시되지 않는 이유에 대한 단서가 제공되지 않습니다. – watkipet
pinvoke marshaller는 구조체를 byte []로 매핑 할 수 없습니다. 이는 의미있는 변환이 아닙니다. 크기 1도 기괴합니다. 이것은 단순한 바이트입니다. byte []와 같은 참조 유형을 값 유형과 겹치게 할 수도 없기 때문에 가비지 수집기는 필드에 참조가 저장되는지 정확하게 확인할 수 없습니다. 고정하는 대신 필드를 고정 크기 버퍼로 선언해야합니다. –