Incorrectly Aligned or Overlapped by a Non-Object Field Error

Incorrectly aligned or overlapped by a non-object field error

The CF Marshaler isn't so good at this type of thing and what you're attempting is unsupported. The problem is that it knows that the first element is unaligned, but it seems to not understand that each element in the array would also be unaligned.

You can see the behavior works in this example:

[StructLayout(LayoutKind.Explicit, Size = 14)]
public struct Message
{
[FieldOffset(0)]
public ushort X;

[FieldOffset(2)]
private ushort Y1;

[MarshalAs(UnmanagedType.LPArray)]
[FieldOffset(4)]
private ushort[] Y2;

[FieldOffset(12)]
public ushort Z;
}

For this type of structure, I never let the marshaler try to handle each of the members anyway. The structure is small, so break out each individual item like this:

[StructLayout(LayoutKind.Explicit, Size = 14)]
public struct Message
{
[FieldOffset(0)]
public ushort X;

[FieldOffset(2)]
private ushort Y1;

[FieldOffset(4)]
private ushort Y2;

[FieldOffset(6)]
private ushort Y3;

[FieldOffset(8)]
private ushort Y4;

[FieldOffset(10)]
private ushort Y5;

[FieldOffset(12)]
public ushort Z;
}

or use a simulated "union" like this:

public struct Y
{
public ushort a;
public ushort b;
public ushort c;
public ushort d;
public ushort e;
}

[StructLayout(LayoutKind.Explicit, Size = 14)]
public struct Message
{
[FieldOffset(0)]
public ushort X;

[FieldOffset(2)]
private Y Y;

[FieldOffset(12)]
public ushort Z;
}

C Union in C# Error incorrectly aligned or overlapped by a non-object field

With the help of others, we have finally got the structures worked out. Here are the 2 structs dealing with the union:

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_GET_STREAM_UNION
{
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 492, ArraySubType = UnmanagedType.I1)]
public byte[] byUnion;
public void Init()
{
byUnion = new byte[492];
}
}

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_STREAM_MODE
{
public byte byGetStreamType;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
public byte[] byRes;
public NET_DVR_GET_STREAM_UNION uGetStream;
public void Init()
{
byGetStreamType = 0;
byRes = new byte[3];
uGetStream.Init();
}
}

Basically, we just use a byte[] for the union for the anonymous data. Then when we do the call, we can use byGetStreamType in NET_DVR_STREAM_MODE as a switch to parse/cast the byte[] to the appropriate type.

Thanks for the input from everyone who helped.

Incorrectly-aligned/non-object field in struct

Arrays must start on 4-byte boundaries.

See this article for more information on using arrays in explicit structs. It also mentions the even boundary issue for arrays, and describes some alternative options for arrays in explicit structs.

http://www.developerfusion.com/article/84519/mastering-structs-in-c/

see also Incorrectly aligned or overlapped by a non-object field error

IMAGE_NT_HEADERS in C# (incorrectly aligned or overlapped by a non-object field)

It should be like this. you are using wrong value

[FieldOffset(16)]
public UInt16 SizeOfOptionalHeader;
[FieldOffset(18)]
public UInt16 Characteristics;

Unions in C# - incorrectly aligned or overlapped with a non-object field

Just use the A/B/C/D structs directly and skip the union. In your extern calls, simply substitute the correct struct in the method declaration.

extern void UnionMethodExpectingA( A a );

If the unmanaged methods actually accept a union and behave differently based on the type passed, then you can declare different extern methods that all end up calling the same unmanaged entry point.

[DllImport( "unmanaged.dll", EntryPoint="ScaryMethod" )]
extern void ScaryMethodExpectingA( A a );

[DllImport( "unmanaged.dll", EntryPoint="ScaryMethod" )]
extern void ScaryMethodExpectingB( B b );

Updated for "length" parameter. The logic still applies. Just create a "wrapper" method and do the same thing.

void CallScaryMethodExpectingA( A a )
{
ScaryMethodExpectingA( a, Marshal.SizeOf( a ) );
}

Incorrectly Aligned Field

You should remove all the FieldOffset attributes and implement the unions outside of the DeviceModeStruct structure. Like this:

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
struct DeviceModeUnion
{
[FieldOffset(0)]
PrinterOnlyFields Printer;
[FieldOffset(0)]
Point Position;
[FieldOffset(0)]
DisplayOnlyFields Display;
}

....

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct DeviceModeStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public ushort dmSpecVersion;
public ushort dmDriverVersion;
public ushort dmSize;
public ushort dmDriverExtra;
public uint dmFields;
public DeviceModeUnion union;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public ushort dmLogPixels;
public uint dmBitsPerPel;
public uint dmPelsWidth;
public uint dmPelsHeight;
public uint dmDisplayFlags;
public uint dmDisplayFrequency;
public uint dmICMMethod;
public uint dmICMIntent;
public uint dmMediaType;
public uint dmDitherType;
public uint dmReserved1;
public uint dmReserved2;
public uint dmPanningWidth;
public uint dmPanningHeight;
}

I've not checked DeviceModeStruct carefully against the documentation, but I am sure you can do that. However, I can confirm that this struct definition at least has the correct size, when compared against the size of the struct defined in the C++ header file.

Union in C# with string incorrectly aligned

What you are trying to do is not legal. String is a reference type and can't be overlapped with anything else in a union. It matters a great deal to the garbage collector, it can't reliable figure out what reference is stored in a field so it cannot reliable figure out if the string object needs to be kept alive.

What's bizarro about your structs is that you overlap a string with a string. Which would technically work, no reason for the garbage collector to be confused since it always sees a valid object reference. But it doesn't actually handle that special case, Microsoft didn't write enough code, or cared to burn the cpu cycles, to check for the type identity.

And that's for a good reason because you don't have to overlap them in your declaration. No point for Microsoft to write the special code to recognize the overlap when you can trivially avoid it.

And is turtles all the way down in your example, every field of union is identical. So there isn't any point at all in using a union.

So don't.



Related Topics



Leave a reply



Submit