Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
572 views
in Technique[技术] by (71.8m points)

.net - C# StructLayout.Explicit Question

I'm trying to understand why the second example below works with no issues, but the first example gives me the exception below. It seems to me that both examples should give an exception based on the description. Can anyone enlighten me?

Unhandled Exception: System.TypeLoadException: Could not load type 'StructTest.OuterType' from assembly 'StructTest, 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.
at StructTest.Program.Main(String[] args) Press any key to continue . . .

Example 1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace StructTest
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct InnerType
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
        char[] buffer;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct OuterType
    {
        [FieldOffset(0)]
        int someValue;

        [FieldOffset(0)]
        InnerType someOtherValue;
    }

    class Program
    {
        static void Main(string[] args)
        {
            OuterType t = new OuterType();
            System.Console.WriteLine(t);
        }
    }
}

Example 2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace StructTest
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct InnerType
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
        char[] buffer;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct OuterType
    {
        [FieldOffset(4)]
        private int someValue;

        [FieldOffset(0)]
        InnerType someOtherValue;

    }

    class Program
    {
        static void Main(string[] args)
        {
            OuterType t = new OuterType();
            System.Console.WriteLine(t);
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The common language runtime contains a verifier that makes sure the running code (verifiable IL) cannot possibly corrupt memory in the managed environment. This prevents you to declare such a structure in which fields overlap. Basically, your struct contains two data members. One integer (which is 4 bytes) and a native integer (pointer size). On a 32 bit CLR, in which you are probably running your code, the char[] will take 4 bytes so if you put the integer less than four bytes away from the beginning of the struct, you'll have overlapping fields. It's interesting to note that both of your code snippets with fail on a 64 bit runtime, as the pointer size is 8 bytes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...