Nachdem wir kürzlich auf .net 4.6 aktualisiert haben, haben wir einen Fehler entdeckt, bei dem RyuJit falsche Ergebnisse liefert. Wir konnten das Problem jetzt umgehen, indem wir in der app.config useLegacyJit enabled = "true" hinzufügen.RyuJit produziert falsche Ergebnisse
Wie kann ich den Maschinencode debuggen, der durch folgende generiert wird?
Ich habe ein neues Konsolen-Projekt in VS 2015 RTM erstellt, auf Release, Any CPU gesetzt, nicht aktiviert 32-Bit-Vorlauf, läuft mit und ohne Debugger angeschlossen erzeugt das gleiche Ergebnis.
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();
}
}
}
}
sollten Sie folgendes Ergebnis: Falsch Falsch
sondern es produziert: Wahr Falsch
Der wichtigste Teil des Beispiels ist
result = true ? false : result;
Welche sollte immer Rückkehr falsch, aber wie Sie aus der Ausgabe sehen können, gibt es True beim ersten Mal t Die Methode wird ausgeführt, und beim zweiten Mal wird die Methode ausgeführt. Wenn Sie einige weitere Zeilen aus der Calculate() -Methode entfernen, wird immer "True" zurückgegeben, aber das angegebene Beispiel ist das, was ich meinem tatsächlichen Produktionsszenario am nächsten bringen könnte.
Ja, es ist ein Inline-Optimierungsfehler. Die erste inline Calculate() hat eine schlechte Anweisung. Sieht für mich aus, dass irgendwo im Optimierer ein '!' Steht, das nicht da sein sollte. Nichts, was wir tun können, um diesen Fehler zu beheben, können Sie natürlich unter connect.microsoft.com melden. Legen Sie das MethodImplOptions.AggressiveInlining für eine Weile weg, das ist wahrscheinlich nicht ausgiebig getestet worden. –
Der tatsächliche Produktionscode verfügt nicht über das AggressiveInlining-Attribut, aber das ist die einzige Möglichkeit, das Verhalten in diesem kleinen Beispiel zu reproduzieren. Der Produktionscode wird teilweise maschinell erzeugt, weshalb der Beispielcode etwas merkwürdig aussieht. Ich habe es gerade gemeldet unter https://connect.microsoft.com/VisualStudio/feedback/details/1578173 – BrandonAGr
@BrandonAGr Dieser Fehler wird beim Inlining verursacht? Die Verwendung von 'MethodImplOptions.NoInlining' ist eine mögliche Umgehung? – Andre