搞乱StructLayouts时发生FatalExecutionEngineError

时间:2014-11-28 20:02:19

标签: c# dynamic structlayout

我在使用structlayouts搞乱了,我发现了一些我觉得很奇怪的事情:

以下代码正如我所想的那样工作:

using System;
using System.Runtime.InteropServices;
public class Program
{
    [STAThread]
    static void Main()
    {
        Magic m = new Magic 
        { 
            InstanceA = new ClassA(), 
            InstanceB = new ClassB {Value="47"} 
        };

        Console.WriteLine(m.InstanceA.Value);
        Console.ReadKey();
    }

    class ClassA
    {
        public dynamic Value;
    }

    class ClassB
    {
        public string Value; // Change to int and it will get messy
    }

    [StructLayout(LayoutKind.Explicit)]
    struct Magic
    {
        [FieldOffset(0)]
        public ClassA InstanceA;
        [FieldOffset(0)]
        public ClassB InstanceB;
    }
}

但是,如果将classB.Value更改为int,则此代码将抛出提到的FatalExecutionEngineError。

任何人都可以解释为什么或者如何解决问题?我知道这可能太复杂了,我只是在这里搞乱,但有人可能想要一些挑战。

1 个答案:

答案 0 :(得分:0)

基本上,你所做的是完全未定义的。你是以两种非常讨厌的方式欺骗​​它:

  • 假装一个非null类引用实际上是一个不同的类型(但没有进行类型检查就完成了)
  • 试图从object加载dynamic引用(object只是int带有一些花哨的编译器技巧)(注意;在所有情况下,这都会很可能指向垃圾;在x64的情况下,它甚至不是整个宽度,因此它将把垃圾读入取消引用的值

基本上:不要那样做。这就是为什么显式布局被视为无法验证的代码。至于如何“正确”(并且我慷慨地使用该术语):

class Magic
{
    private object val;
    public ClassA InstanceA { get { return (InstanceA)val;} set { val = value; } }
    public ClassB InstanceB { get { return (InstanceB)val;} set { val = value; } }
}

如果您希望val as Foo看到另一种类型,也可以使用(Foo)val代替null