Considerar:
using System;
public class Test
{
enum State : sbyte { OK = 0, BUG = -1 }
static void Main(string[] args)
{
var s = new State[1, 1];
s[0, 0] = State.BUG;
State a = s[0, 0];
Console.WriteLine(a == s[0, 0]); // False
}
}
¿Cómo se puede explicar esto? Se produce en versiones de depuración en Visual Studio 2015 cuando se ejecuta en el xIT JIT. Una compilación de lanzamiento o ejecución en el x64 JIT imprime True como se esperaba.
Para reproducir desde la línea de comando:
csc Test.cs /platform:x86 /debug
( /debug:pdbonly
, /debug:portable
Y /debug:full
también reproducirse.)
ildasm
y luegoilasm
"soluciones" que .../debug=IMPL
bandera la deja rota;/debug=OPT
"lo arregla".Respuestas:
Encontró un error de generación de código en .NET 4 x86 jitter. Es muy inusual, solo falla cuando el código no está optimizado. El código de la máquina se ve así:
Un asunto pesado con muchos temporales y duplicación de código, eso es normal para el código no optimizado. La instrucción en 013F04B8 es notable, ahí es donde ocurre la conversión necesaria de sbyte a un entero de 32 bits. La función auxiliar de obtención de matriz devolvió 0x0000000FF, igual a State.BUG, y eso debe convertirse a -1 (0xFFFFFFFF) antes de que se pueda comparar el valor. La instrucción MOVSX es una instrucción Sign eXtension.
Lo mismo sucede nuevamente en 013F04CC, pero esta vez no hay instrucciones MOVSX para hacer la misma conversión. Ahí es donde se caen los chips, la instrucción CMP compara 0xFFFFFFFF con 0x000000FF y eso es falso. Entonces, este es un error de omisión, el generador de código no pudo emitir MOVSX nuevamente para realizar la misma conversión de sbyte a int.
Lo que es particularmente inusual acerca de este error es que funciona correctamente cuando habilita el optimizador, ahora sabe usar MOVSX en ambos casos.
La razón probable de que este error no se haya detectado durante tanto tiempo es el uso de sbyte como el tipo base de la enumeración. Muy raro de hacer. El uso de una matriz multidimensional también es instrumental, la combinación es fatal.
De lo contrario, diría que es un error bastante crítico. Es difícil adivinar cuán extendido podría ser, solo tengo que probar la fluctuación de fase 4.6.1 x86. El x64 y el jitter 3.5 x86 generan un código muy diferente y evitan este error. La solución temporal para continuar es eliminar sbyte como el tipo base enum y dejar que sea el valor predeterminado, int , para que no sea necesaria la extensión de signo.
Puede presentar el error en connect.microsoft.com, el enlace a este Q + A debería ser suficiente para decirles todo lo que necesitan saber. Avísame si no quieres tomarte el tiempo y yo me encargaré.
fuente
byte
lugar desbyte
debería estar bien también y podría ser preferible si el código real se usa con decir un ORM donde no desea que sus banderas en la base de datos ocupen espacio adicional.Consideremos la declaración de OP:
Dado que el error solo ocurre cuando
BUG
es negativo (de -128 a -1) y el estado es una enumeración de bytes firmados , comencé a suponer que había un problema de transmisión en alguna parte.Si ejecuta esto:
saldrá:
Por una razón que ignoro (a partir de ahora)
s[0, 0]
se convierte en un byte antes de la evaluación y es por eso que afirma quea == s[0,0]
es falso.fuente