C# 表达式 - FatalExecutionEngineError
C# Expressions - FatalExecutionEngineError
今天我正在调试我的一些代码,这些代码构建了一些 ExpressionTrees,将它们编译为可调用的委托,然后在需要时调用它们。在执行此操作时,我遇到了 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);
}
}
}
你的重现代码非常好,这个炸弹可靠。它高度特定于 32 位代码的 v4 调试引擎,它不会出现在 v2 引擎或 64 位调试器引擎中。新旧v4引擎都有这个问题
我在调试调试器时没有看到太多可识别的东西,失败的代码位于 mscorlib.dll 中,带有显式 throw。不熟悉,我看到一些关于名为 ILTree
的非托管 class 的提示。不是 Microsoft 与我们分享的东西,它不存在于参考源、SSCLI20 或 CoreCLR 源代码中。
这是微软要担心的事情。通过 connect.microsoft.com 报告错误。这个 SO 问题的 link 应该足以记录它。如果您不想花时间去做,请告诉我,我会处理。
与此同时,您确实有一个不错的解决方法可以继续进行,只需通过移除抖动强制让您的程序 运行 处于 64 位模式。 Project + Properties,Build 选项卡,取消选中 "Prefer 32-bit" 选项和平台目标的 select AnyCPU。请在收到 Microsoft 的回复后跟进。
今天我正在调试我的一些代码,这些代码构建了一些 ExpressionTrees,将它们编译为可调用的委托,然后在需要时调用它们。在执行此操作时,我遇到了 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);
}
}
}
你的重现代码非常好,这个炸弹可靠。它高度特定于 32 位代码的 v4 调试引擎,它不会出现在 v2 引擎或 64 位调试器引擎中。新旧v4引擎都有这个问题
我在调试调试器时没有看到太多可识别的东西,失败的代码位于 mscorlib.dll 中,带有显式 throw。不熟悉,我看到一些关于名为 ILTree
的非托管 class 的提示。不是 Microsoft 与我们分享的东西,它不存在于参考源、SSCLI20 或 CoreCLR 源代码中。
这是微软要担心的事情。通过 connect.microsoft.com 报告错误。这个 SO 问题的 link 应该足以记录它。如果您不想花时间去做,请告诉我,我会处理。
与此同时,您确实有一个不错的解决方法可以继续进行,只需通过移除抖动强制让您的程序 运行 处于 64 位模式。 Project + Properties,Build 选项卡,取消选中 "Prefer 32-bit" 选项和平台目标的 select AnyCPU。请在收到 Microsoft 的回复后跟进。