Search code examples
c#c++marshallingstructlayout

Marshal.Sizeof() returning unexpected value


I'm debugging code in C# written by a 3rd party. The project is an old C++ project that was rewritten in C# by a contractor, and I have no access to the contractor. I authored the original C++ version.

The issue is when the C# code gets the size of a structure that represents data received over a UDP connection.

The struct is defined as:

[StructLayout(LayoutKind.Sequential,Pack=1)]
internal class PROXY_HDR {
    public ushort pad;
    public ushort label;
    public char flags;
    public ushort length;
    public char[] ip = new char[4];
    public ushort port;
}

The size of this struct is retrieved as:

int size = Marshal.Sizeof(typeof(PROXY_HDR));

and the value returned is 17 instead of the expected 13. With a 4-byte difference, I suspect the ip member, but only because it's expressed differently than the other members (with 'new'), but I have no other basis to decide.

I don't typically use this type of marshaling in my C# code that parses received packets without a problem, so I don't know how to modify this struct definition to make it 'line up' with the original version size-wise.

I could replace the Marshal line with

int size = 13;

but that's cheating, right?

Can I modify this layout somehow to get the size to come out right?


Solution

  • Add this to the structure:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal class PROXY_HDR
    {
        public ushort pad;
        public ushort label;
        public byte flags;
        public ushort length;
        [MarshalAs(UnmanagedType.ByValArray,
            SizeConst = 4, ArraySubType = UnmanagedType.U1)]
        public byte[] ip;
        public ushort port;
    }
    

    This will tell the compiler to treat it as a typical C-style array, not a pointer. This should be byte, as an IP address is an unsigned char array. char typically isn't used in these types of headers, it's usually byte (i.e: unsigned char)