为什么会发生CLR异常FatalExecutionEngineError? [英] Why CLR Exception FatalExecutionEngineError happens?

查看:168
本文介绍了为什么会发生CLR异常FatalExecutionEngineError?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用的是一个封装数字值的结构,我发现在表达式中使用该结构的可空版本时,会发生 FatalExecutionEngineError

We are using a struct that encapsulates numeric values and I found out when the nullable version of this struct is used in an expression, a FatalExecutionEngineError happens:


其他信息:运行时遇到致命错误。错误的
地址位于线程0x52d8上的0x729c1e04。错误
代码为0xc0000005。此错误可能是CLR或用户代码的
不安全或不可验证部分中的错误。此
错误的常见来源包括COM-interop或PInvoke的用户封送处理错误,这些错误可能导致
破坏堆栈。

Additional information: The runtime has encountered a fatal error. The address of the error was at 0x729c1e04, on thread 0x52d8. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

我正在使用Visual Studio Premium 2013 Update 3
这是源代码(C#,目标.NET Framework 4.5):

I am using Visual Studio Premium 2013 Update 3 Here is the source code (C#, target .NET Framework 4.5):

using System;
using System.Globalization;
namespace ConsoleApplication4
{
    public struct Number
    {
        ValueType _val;

        private Number(double val)
        {
            this._val = val;
        }

        public static implicit operator double(Number val)
        {
            return Convert.ToDouble(val._val, CultureInfo.InvariantCulture);
        }

        public static implicit operator Number(double val)
        {
            return new Number(val);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Number? b = 1.2;
            var c = b - 1.2;

            Number b1 = 1.2;
            var c1 = b1 - 1.2;
        }
    }
}

请注意,添加此选项可以解决问题,因此并不紧急,但是我非常感兴趣为什么这个问题实际上正在发生。

Note, adding this solves the issue, so it is not urgent, however I am very interested why this issue is actually happening.

public static implicit operator double(Number? val)
{
    return Convert.ToDouble(val.GetValueOrDefault()._val, CultureInfo.InvariantCulture);
}


推荐答案

这看起来像是编译器错误。问题发生在 Main 的第二行。

This looks like a compiler bug. The problem happens on the second line of Main.

        Number? b = 1.2;
        var c = b - 1.2; // The problem lies here

请注意VS2013生成的IL,问题出在 IL_005C 和不必要的环绕代码:

Note the IL generated by VS2013, the issue is with IL_005C and surrounded code, which is unnecessarily generated:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       116 (0x74)
  .maxstack  2
  .locals init (valuetype [mscorlib]System.Nullable`1<valuetype Test.Number> V_0,
           valuetype [mscorlib]System.Nullable`1<float64> V_1,
           valuetype [mscorlib]System.Nullable`1<valuetype Test.Number> V_2,
           valuetype [mscorlib]System.Nullable`1<float64> V_3,
           valuetype [mscorlib]System.Nullable`1<float64> V_4)

// Number? b = 1.2;
  IL_0000:  nop
  IL_0001:  ldloca.s   V_0 //b
  IL_0003:  ldc.r8     1.2
  IL_000c:  call       valuetype Test.Number Test.Number::op_Implicit(float64)
  IL_0011:  call       instance void valuetype [mscorlib]System.Nullable`1<valuetype Test.Number>::.ctor(!0)
  IL_0016:  nop
  IL_0017:  ldloc.0
  IL_0018:  stloc.2    // b

// var c = b - 1.2;
  IL_0019:  ldloca.s   V_2 // b
  IL_001b:  call       instance bool valuetype [mscorlib]System.Nullable`1<valuetype Test.Number>::get_HasValue()
  IL_0020:  brtrue.s   IL_002d
  IL_0022:  ldloca.s   V_3
  IL_0024:  initobj    valuetype [mscorlib]System.Nullable`1<float64>
  IL_002a:  ldloc.3
  IL_002b:  br.s       IL_003e
  IL_002d:  ldloca.s   V_2
  IL_002f:  call       instance !0 valuetype [mscorlib]System.Nullable`1<valuetype Test.Number>::GetValueOrDefault()
  IL_0034:  call       float64 Test.Number::op_Implicit(valuetype Test.Number)

  // Um, what? First part of compiler bug is that it's needlessly creating a nullable float
  IL_0039:  newobj     instance void valuetype [mscorlib]System.Nullable`1<float64>::.ctor(!0)
  IL_003e:  nop
  IL_003f:  stloc.3
  IL_0040:  ldloca.s   V_3
  IL_0042:  call       instance bool valuetype [mscorlib]System.Nullable`1<float64>::get_HasValue()
  IL_0047:  brtrue.s   IL_0055
  IL_0049:  ldloca.s   V_4
  IL_004b:  initobj    valuetype [mscorlib]System.Nullable`1<float64>
  IL_0051:  ldloc.s    V_4
  IL_0053:  br.s       IL_0071
  IL_0055:  ldloca.s   V_3

  // Here's the real bug, though.  It's passing float64 to a the op_Implicit that is expecting a Number struct
  IL_0057:  call       instance !0 valuetype [mscorlib]System.Nullable`1<float64>::GetValueOrDefault()
  IL_005c:  call       float64 Test.Number::op_Implicit(valuetype Test.Number)
  IL_0061:  conv.r8


  IL_0062:  ldc.r8     1.2
  IL_006b:  sub
  IL_006c:  newobj     instance void valuetype [mscorlib]System.Nullable`1<float64>::.ctor(!0)
  IL_0071:  nop
  IL_0072:  stloc.1
  IL_0073:  ret
} // end of method Program::Main

Roslyn(也是VS14 CTP,使用它)产生没有此问题的其他IL。该代码几乎相同,只是它省略了 IL_0039 IL_0061 之间的IL。

Roslyn (also VS14 CTP, which uses it) produces different IL which doesn't have this issue. The code is almost identical, except that it omits the IL between IL_0039 and IL_0061.

这篇关于为什么会发生CLR异常FatalExecutionEngineError?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆