首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么会发生CLR FatalExecutionEngineError异常?

为什么会发生CLR FatalExecutionEngineError异常?
EN

Stack Overflow用户
提问于 2014-08-27 00:34:13
回答 1查看 7.2K关注 0票数 19

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

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

我使用的是Visual Studio Premium 2013更新3,这里是源代码(C#,目标.NET Framework4.5):

代码语言:javascript
复制
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;
        }
    }
}

注意,添加这个解决了这个问题,所以它不是紧急的,但是我非常感兴趣为什么这个问题实际上会发生。

代码语言:javascript
复制
public static implicit operator double(Number? val)
{
    return Convert.ToDouble(val.GetValueOrDefault()._val, CultureInfo.InvariantCulture);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-27 01:31:17

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

代码语言:javascript
复制
        Number? b = 1.2;
        var c = b - 1.2; // The problem lies here

注意VS2013生成的IL,问题出在IL_005C和周围的代码上,这是不必要的生成:

代码语言:javascript
复制
.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_0039IL_0061之间的IL。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25510837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档