Po aktualizacji do .net 4.6 odkryliśmy błąd, w którym RyuJit generuje niepoprawne wyniki, mogliśmy na razie obejść ten problem, dodając useLegacyJit enabled = "true" do pliku app.config.RyuJit produkuje niepoprawne wyniki
Jak mogę debugować kod maszynowy wygenerowany przez następujące elementy?
Utworzony nowy projekt konsoli w VS 2015 RTM, ustawiony na Release, Dowolny CPU, niezaznaczony Woliera 32-bitowy, uruchomiony z dołączonym debugerem i bez niego daje taki sam wynik.
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();
}
}
}
}
Należy produkować: fałszywy fałszywy
lecz produkuje: Prawdziwa fałszywy
Kluczową częścią przykładem jest
result = true ? false : result;
który powinien zawsze wracają false, ale jak widać na wyjściu, zwraca True po raz pierwszy t metoda jest uruchomiona, a inna odpowiedź po drugim uruchomieniu metody. Usunięcie kilku kolejnych linii z metody Calculate() spowoduje, że powróci ona zawsze True, ale podany przykład jest najbliższy mojemu powieleniu do naszego rzeczywistego scenariusza produkcji.
Tak, jest to błąd optymalizacji inline. Pierwszy wbudowany Calculate() ma złą instrukcję. Wygląda mi na to, że gdzieś wewnątrz optymalizatora jest '!', Którego tam nie powinno być. Nic nie możemy zrobić, aby naprawić ten błąd oczywiście, możesz zgłosić to na connect.microsoft.com. Po prostu zwolnij metodę MethodImplOptions.AggressiveInlining przez pewien czas, co jest mało prawdopodobne, aby zostało szeroko przetestowane. –
Rzeczywisty kod produkcyjny nie ma atrybutu AggressiveInlining, ale jest to jedyny sposób, w jaki mogę odtworzyć zachowanie w tym małym przykładzie. Kod produkcyjny jest częściowo generowany maszynowo, dlatego przykładowy kod wygląda nieco dziwnie. Właśnie zgłosiłem to na https://connect.microsoft.com/VisualStudio/feedback/details/1578173 – BrandonAGr
@BandandAGr Ten błąd jest spowodowany podczas wstawiania? Korzystanie z 'MethodImplOptions.NoInlining' jest możliwym obejściem? – Andre