È stato trovato un bug di generazione del codice nel jitter .NET 4 x86. È molto insolito, fallisce solo quando il codice non è ottimizzato. Il codice macchina è simile al seguente:
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
Un affare plodding con molti provvisori e duplicazione del codice, questo è normale per il codice non ottimizzato. L'istruzione su 013F04B8 è notevole, ovvero dove si verifica la conversione necessaria da sbyte a un numero intero a 32 bit. La funzione di aiuto getter dell'array ha restituito 0x0000000FF, uguale a State.BUG, e deve essere convertito in -1 (0xFFFFFFFF) prima di poter confrontare il valore. L'istruzione MOVSX è un'istruzione Sign eXtension.
La stessa cosa accade di nuovo a 013F04CC, ma questa volta non c'è alcuna istruzione MOVSX per fare la stessa conversione. Ecco dove cadono i chip, l'istruzione CMP confronta 0xFFFFFFFF con 0x000000FF e questo è falso. Quindi questo è un errore di omissione, il generatore di codice non è riuscito a emettere di nuovo MOVSX per eseguire lo stesso sbyte nella conversione int.
Ciò che è particolarmente insolito di questo bug è che funziona correttamente quando si abilita l'ottimizzatore, ora sa usare MOVSX in entrambi i casi.
La probabile ragione per cui questo bug non è stato rilevato per così tanto tempo è l'uso di sbyte come tipo base dell'enum. Abbastanza raro da fare. Anche l'utilizzo di un array multidimensionale è strumentale, la combinazione è fatale.
Altrimenti direi un bug piuttosto critico. Quanto sia diffuso è difficile da indovinare, ho solo il jitter 4.6.1 x86 da testare. Il jitter x64 e 3.5 x86 generano un codice molto diverso ed evitano questo errore. La soluzione temporanea per continuare è rimuovere sbyte come tipo di base enum e lasciarlo come predefinito, int , quindi non è necessaria l'estensione del segno.
Puoi segnalare il bug su connect.microsoft.com, il collegamento a questo Q + A dovrebbe essere sufficiente per dire loro tutto ciò che devono sapere. Fammi sapere se non vuoi prenderti il tempo e me ne occuperò io.