Sie haben einen Code-Generierungsfehler im .NET 4 x86-Jitter gefunden. Es ist sehr ungewöhnlich, es schlägt nur fehl, wenn der Code nicht optimiert ist. Der Maschinencode sieht wie folgt aus:
State a = s[0, 0];
013F04A9 push 0 ; index 2 = 0
013F04AB mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04AE xor edx,edx ; index 1 = 0
013F04B0 call 013F0058 ; eax = s[0, 0]
013F04B5 mov dword ptr [ebp-4Ch],eax ; $temp1 = eax
013F04B8 movsx eax,byte ptr [ebp-4Ch] ; convert sbyte to int
013F04BC mov dword ptr [ebp-44h],eax ; a = s[0, 0]
Console.WriteLine(a == s[0, 0]); // False
013F04BF mov eax,dword ptr [ebp-44h] ; a
013F04C2 mov dword ptr [ebp-50h],eax ; $temp2 = a
013F04C5 push 0 ; index 2 = 0
013F04C7 mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04CA xor edx,edx ; index 1 = 0
013F04CC call 013F0058 ; eax = s[0, 0]
013F04D1 mov dword ptr [ebp-54h],eax ; $temp3 = eax
; <=== Bug here!
013F04D4 mov eax,dword ptr [ebp-50h] ; a == s[0, 0]
013F04D7 cmp eax,dword ptr [ebp-54h]
013F04DA sete cl
013F04DD movzx ecx,cl
013F04E0 call 731C28F4
Eine Plackerei Angelegenheit mit vielen Provisorien und Code-Duplizierung, das ist normal, nicht optimierten Code. Bemerkenswert ist der Befehl bei 013F04B8, bei dem die notwendige Konvertierung von sbyte in eine 32-Bit-Ganzzahl erfolgt. Die Array-Getter-Hilfsfunktion hat 0x0000000FF zurückgegeben, entspricht State.BUG und muss in -1 (0xFFFFFFFF) konvertiert werden, bevor der Wert verglichen werden kann. Die MOVSX-Anweisung ist eine Sign eXtension-Anweisung.
Das gleiche passiert wieder bei 013F04CC, aber dieses Mal gibt es keine MOVSX Anweisung, um die gleiche Konvertierung zu machen. Dort fallen die Chips, der CMP-Befehl vergleicht 0xFFFFFFFF mit 0x000000FF und das ist falsch. Dies ist also ein Fehler der Auslassung, der Code-Generator konnte MOVSX nicht erneut ausgeben, um die gleiche Umwandlung von sbyte nach int durchzuführen.
Was an diesem Fehler besonders ungewöhnlich ist, ist, dass dies korrekt funktioniert, wenn Sie den Optimierer aktivieren, er kann jetzt in beiden Fällen MOVSX verwenden.
Der mögliche Grund, dass dieser Fehler so lange unentdeckt blieb, ist die Verwendung von sbyte als Basistyp der Enumeration. Sehr selten zu tun.Die Verwendung eines multidimensionalen Arrays ist ebenfalls instrumentell, die Kombination ist fatal.
Sonst ein ziemlich kritischer Fehler würde ich sagen. Wie weit verbreitet es ist, ist schwer zu erraten, ich habe nur den 4.6.1 x86 Jitter zu testen. Der x64- und der 3,5x86-Jitter erzeugen einen sehr unterschiedlichen Code und vermeiden diesen Fehler. Die temporäre Problemumgehung zum Fortfahren besteht darin, sbyte als Enum-Basistyp zu entfernen und den Standardwert int zu definieren, sodass keine Zeichenerweiterung erforderlich ist.
Sie können den Fehler bei connect.microsoft.com ablegen, die Verknüpfung zu diesem Q + A sollte ausreichen, um ihnen alles zu erzählen, was sie wissen müssen. Lass es mich wissen, wenn du dir nicht die Zeit nehmen willst und ich werde mich darum kümmern.
https://ideone.com/li3EzY es ist wahr. Fügen Sie weitere Informationen über .NET-Version, IDE, Compiler – Backs
hinzu Ich sehe diese Rückgabe falsch unter einem Debug-Build, aber kein Release-Build, Targeting .Net 4.6.2 in VS2015. –
Das gleiche hier. Aber nachdem ich mit den Projekteinstellungen herumgespielt hatte, fand ich heraus, dass das Häkchen bei "Prefer 32 bit" in der "Build" -Registerkarte wie gewünscht funktioniert - und "True" zurückgibt. Es sieht für mich wie ein WoW64-Problem aus. –