我们最近升级到.net 4.6后发现一个错误,RyuJit生成了不正确的结果。我们目前通过在app.config中添加useLegacyJit enabled="true"来解决此问题。
如何调试以下代码生成的机器码?
我在VS 2015 RTM中创建了一个新的控制台项目,设置为Release、Any CPU,取消选中Prefer 32位,在运行时使用/不使用附加的调试器产生相同的结果。
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Calculate());
Console.WriteLine(Calculate());
Console.ReadLine();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Value Calculate()
{
bool? _0 = (bool?)null;
bool? _1 = (bool?)true;
if (!Value.IsPresent<bool>(_1))
{
return default(Value);
}
bool? result = null;
result = (_1.Value ? new bool?(false) : result);
if (_0.HasValue && _0.Value)
{
}
return new Value(result);
}
public struct Value
{
bool? _value;
public Value(bool? value)
{
_value = value;
}
public static bool IsPresent<T>(bool? _)
{
return _.HasValue;
}
public override string ToString()
{
return _value.ToString();
}
}
}
}
它应该产生: False False
但实际上它产生了: True False
这个例子的关键部分是
result = true ? false : result;
这个方法应该总是返回false,但是从输出可以看出,第一次运行时它却返回了True,第二次运行则返回了不同的答案。从Calculate()方法中删除更多的行将导致它总是返回True,但是给定的示例是我能够重现我们实际生产场景的最接近的情况。
!
符号。当然我们无法修复这个错误,你可以在connect.microsoft.com上报告它。暂时停用MethodImplOptions.AggressiveInlining,在编写代码时避免过度使用,因为这可能没有经过充分测试。 - Hans PassantMethodImplOptions.NoInlining
是一个可能的解决方法吗? - Ortiga