What's the cause of this FatalExecutionEngineError in .NET 4.5 beta?
下面的示例代码是自然发生的。突然间,我的代码出现了一个听起来很讨厌的
1 2 3 4 5 6 7 8 9 10 11 | class A<T> { static A() { } public A() { string.Format("{0}", string.Empty); } } class B { static void Main() { new A<object>(); } } |
应在.NET Framework 4和4.5上产生此错误:
这是一个已知的错误吗?原因是什么?我能做些什么来减轻它?我目前的工作是不使用
我在我的笔记本电脑上试过这个代码,但没有抱怨。但是,我确实尝试了我的主应用程序,它也在笔记本电脑上崩溃了。我一定是在减少问题的时候弄坏了什么东西,我看看能不能弄清楚是什么。
我的笔记本电脑和上面的代码一样崩溃了,框架4.0,但主要崩溃了,即使是4.5。两个系统都在使用最新更新的vs'12(7月?).
更多信息:
- IL代码(编译的调试/any cpu/4.0/vs2010(IDE不重要吗?):http://codepad.org/bozdd98e
- 与2010年4.0相比,还没有见过。不与优化一起崩溃/不与优化一起崩溃、不同的目标CPU、附加/不附加调试程序等。—蒂姆·梅多拉
- 如果我使用anycpu,在2010年崩溃,在x86中很好。在使用平台target=anycpu的Visual Studio 2010 SP1中崩溃,但在平台target=x86时很好。这台机器也安装了VS2012RC,因此4.5可能会进行就地更换。使用anycpu和targetplatform=3.5,那么它不会崩溃,因此看起来像是框架中的回归。
- 无法在带有4.0的vs2010中的x86、x64或anycpu上复制。富士
- 仅适用于X64(2012RC,FX4.5)-Henk Holterman
- 在Win8 RP上的VS2012 RC。最初在以.NET 4.5为目标时没有看到此MDA。当切换到目标.NET 4.0时,出现了MDA。然后在切换回.NET 4.5之后,MDA仍然存在。-韦恩
我相信我已经找到了一个很好的解释,因为我们会发现没有来自.NET JIT团队的人回答。好的。 更新好的。 我看得更深了一点,我相信我找到了问题的根源。这似乎是由JIT类型初始化逻辑中的错误和依赖于JIT按预期工作的假设的C编译器中的更改组合造成的。我认为JIT错误存在于.NET 4.0中,但被.NET 4.5编译器中的更改所发现。好的。 我不认为 .NET 4.0 mscorlib.dll中的 在mscorlib.dll的.NET 4.5版本中,
..... No static constructor :( .....
Ok. 在这两个版本中, 我试图创建一个可以类似地编译到IL的类型(这样它就有了静态字段,但没有静态构造函数 我猜在.NET 4.0和4.5之间有两种情况发生了变化:好的。 首先:EE被更改,这样它就可以从非托管代码自动初始化 第二:编译器进行了更改,因此它不会为字符串发出静态构造函数,因为知道将从非托管端分配 似乎EE没有足够快地沿着一些优化路径分配 最后,我相信这个bug表明了JIT类型初始化逻辑中的一个更深层次的问题。似乎编译器中的更改是 原件好的。 首先,哇哦,BCL的人通过一些性能优化变得非常有创造力。许多 我跟着这条线索走了一段时间,但是 不过,我觉得我发现了同一种虫子的奇怪表现。好的。 此代码失败,出现访问冲突:好的。 然而,如果你不理解 okay. 对我来说, okay. FYI here is the jited code for the two versions: okay. okay.ZZU1 okay. 《守则》的其余部分(EDOCX1&1)在两个版本中是相同的。 okay. 编辑 okay. 此外,两种版本中的IL是相同的,但 okay. 版本 okay. 第二 okay. 另一个值得注意的是, okay.好吧 显式声明静态构造函数时,将发出 我猜他们在X64 Jiter上搞砸了这个事实,所以当从一个已经运行了自己的静态构造函数的类中访问不同类型的静态成员时,它会以某种方式跳过静态构造函数的运行(或以错误的顺序执行),从而导致崩溃。(您不会得到空指针异常,可能是因为它不是空初始化的。) 我没有运行您的代码,所以这一部分可能是错误的——但是如果我不得不做另一个猜测,我会说可能是 同样,我还没有测试过它,但这是我对数据的最好猜测。 随时测试我的假设,让我知道它是如何发展的。这也不是一个完整的答案,但我有一些想法。好的。
2
3
4
5
6
7
8
9
void .cctor() cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: ldstr ""
IL_0005: stsfld string System.String::Empty
IL_000a: ret
} // end of method String::.cctor
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
static A() { }
public A(out string s) {
s = string.Empty;
}
}
class B
{
static void Main() {
string s;
new A<object>(out s);
//new A<int>(out s);
System.Console.WriteLine(s.Length);
}
}
2
3
4
5
6
7
8
9
10
11
12
00000000 sub rsp,28h
00000004 mov rax,rdx
s = string.Empty;
00000007 mov rdx,12353250h
00000011 mov rdx,qword ptr [rdx]
00000014 mov rcx,rax
00000017 call 000000005F691160
0000001c nop
0000001d add rsp,28h
00000021 ret
}
我强烈怀疑这是由.NET 4.0中的优化(与
一个观察,但dotpeek显示解压后的字符串。因此为空:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /// <summary> /// Represents the empty string. This field is read-only. /// </summary> /// <filterpriority>1</filterpriority> [__DynamicallyInvokable] public static readonly string Empty; internal sealed class __DynamicallyInvokableAttribute : Attribute { [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public __DynamicallyInvokableAttribute() { } } |
如果我以同样的方式声明我自己的
1 2 3 4 5 6 7 8 9 10 11 | class A<T> { static readonly string Empty; static A() { } public A() { string.Format("{0}", Empty); } } |