【问题标题】:C# Expressions - FatalExecutionEngineErrorC# 表达式 - FatalExecutionEngineError
【发布时间】:2015-02-25 15:03:21
【问题描述】:

今天我正在调试我的一些代码,它构建了一些表达式树,将它们编译为可调用的委托,然后在需要时调用它们。在执行此操作时,我遇到了一个 FatalExecutionEngineError 单步执行代码:

起初我有点震惊,因为我不知道我的表情可能有什么问题,它们看起来都很好。后来我发现这种情况只发生在以下情况:

  • Method A 是一个静态方法,被调用并生成 ExpressionTree,它可能再次包含Expression.Call()Method A。因此,在我为 ExpressionTree 编译 Lambda 之后,如果我在此方法中调用生成的委托(我们称之为 Method B)可能会导致递归......(Method A -> [Generated]Method B -> Method A )。

  • ...这在我的场景中是完全可能的。如上所述,我正在调试这段代码,所以我在Method A 中设置了一个断点。

  • Method A 第一次被常规代码调用,断点照常命中。当Method B被调用时,断点再次命中,仍然一切正常。

  • 但是,当我跳过最后一行离开调试器的第二次调用时,FatalExecutionEngineError 就会出现。

如果我在没有调试的情况下运行代码,或者不进入对Method A 的递归调用,或者如果我不跨过方法的最后一行,则不会出现问题,并且我的表达式代码执行为预计。

我无法确定这是否是 VS-Debugger 或 .NET Framework 中的错误,或者我是否做了一些可怕的、可怕的错误,只有在调试相关行时才会出现。

这是一个非常简单的示例代码,您可以开箱即用。我正在使用 Visual Studio 2013 Prof Update 4 和 .NET 4.5.1。只需在DoSomething() 中设置一个断点,然后尝试单步执行到最后——如果可以的话;)

谁能确认一个错误,或者我的表达式格式不正确?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionProblem
{
    public class MainClass
    {
        public static void DoSomething(bool stop)
        {
            var method = typeof(MainClass).GetMethod(
                "DoSomething",
                BindingFlags.Public | BindingFlags.Static,
                Type.DefaultBinder,
                new Type[] { typeof(bool) },
                null);

            var expParam = Expression.Parameter(typeof(bool), "stop");
            var expCall = Expression.Call(null, method, expParam);
            var lambda = Expression.Lambda(expCall, expParam);
            var @delegate = lambda.Compile();
            if(!stop)
            {
                @delegate.DynamicInvoke(true);
            }
        }

        public static void Main(string[] args)
        {
            DoSomething(false);
        }
    }
}

【问题讨论】:

  • 哇!它工作/爆炸! :-)
  • 我在使用 VS2012 或 VS2010 时得到了同样的结果,但只有在使用您描述的步骤时。如果我踏入@delegate.DynamicInvoke,它只会爆炸,然后继续跨过(不让它运行)。
  • 由于不调试时运行良好,估计是调试器的问题。
  • @Puer VS 2013 Update 4,测试了 32 位和 64 位应用程序
  • 我也遇到过同样的问题。忽略并继续我的其余工作,因为当我们不通过它时它会起作用。如果只安装了 .Net 4.5(或更低版本),则不会发生这种情况。问题从.Net 4.5.1 开始是我发现的。

标签: c# debugging visual-studio-2013 expression expression-trees


【解决方案1】:

您的复制代码非常好,这个炸弹很可靠。它高度特定于 32 位代码的 v4 调试引擎,不会发生在 v2 引擎或 64 位调试器引擎中。新旧v4引擎都有这个问题。

当我调试调试器时,我看不到任何可识别的内容,失败的代码位于 mscorlib.dll 中,并带有显式 throw。没什么熟悉的,我看到了一些关于名为ILTree 的非托管类的提示。不是 Microsoft 与我们共享的东西,它不在参考源、SSCLI20 或 CoreCLR 源代码中。

这是微软需要担心的事情。通过 connect.microsoft.com 报告错误。这个 SO question 的链接应该足以记录它。如果您不想花时间去做,请告诉我,我会处理的。

虽然您确实有一个不错的解决方法可以继续运行,但只需通过消除抖动强制让您的程序在 64 位模式下运行即可。 Project + Properties,Build选项卡,取消勾选“Prefer 32-bit”选项并选择AnyCPU作为Platform target。请在收到 Microsoft 的回复后跟进。

【讨论】:

猜你喜欢
  • 2011-07-23
  • 2015-10-15
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多