2012-06-27 21 views
13

Estoy utilizando Visual Studio 2010 SP1 último en el AC# proyecto de biblioteca de clases (4 .net) y estoy curiosidad por algo ...¿Por qué debería comprobar si tengo un valor mayor que Int32.MaxValue?

Teniendo en cuenta este método:

public void DoSomethingBrilliant(int input) 
{ 
    if (input == int.MaxValue) 
     throw new ArgumentOutOfRangeException("input"); 

    input++; 

    Console.WriteLine(input); 
} 

consigo esta advertencia de análisis de código:

CA2233: Microsoft.Usage: Corregir el desbordamiento potencial en 'de entrada + 1' la operación en 'Test.DoSomethingBrilliant (int)'.

pensé para mí, que es un poco extraño, ya que estoy comprobando que la operación no tendrá input++ desbordamiento lanzando esa excepción elegante al principio pero cambiado a esto:

public void DoSomethingBrilliant(int input) 
{ 
    if (input >= int.MaxValue) 
     throw new ArgumentOutOfRangeException("input"); 

    input++; 

    Console.WriteLine(input); 
} 

y, por supuesto, la advertencia desapareció.

Ahora mi pequeño cerebro está confundido porque dado que estoy obteniendo un int como argumento, ¿por qué la comprobación para ver si es mayor que el valor máximo permitido para un número entero alguna vez proporciona algún valor?

Luego volví al código de código original y cambié a depuración y ¡se construyó sin la advertencia! Curioso y curioso ...

Comprobé las diferencias entre la depuración y la versión y encontré que si selecciono la opción Optimizar el código, la advertencia del análisis del código aparece de nuevo.

Por lo tanto, la optimización da como resultado algo que significa que necesito comprobar más de int.MaxValue. ¿Huh? ¿Por qué? ¿Estoy siendo super denso? ¿Qué ha hecho la optimización que significa que podría obtener un int mayor que int.MaxValue pasado a un método que acepta un int?

O, ¿esto es solo un error en la función de análisis de código?

actualización

Aquí está la IL para la versión "sin optimizar" (donde el análisis de código lo hace bien):

.method public hidebysig instance void DoSomethingBrilliant(int32 input) cil managed 
{ 
    // Code size  40 (0x28) 
    .maxstack 2 
    .locals init ([0] bool CS$4$0000) 
    IL_0000: nop 
    IL_0001: ldarg.1 
    IL_0002: ldc.i4  0x7fffffff 
    IL_0007: ceq 
    IL_0009: ldc.i4.0 
    IL_000a: ceq 
    IL_000c: stloc.0 
    IL_000d: ldloc.0 
    IL_000e: brtrue.s IL_001b 
    IL_0010: ldstr  "input" 
    IL_0015: newobj  instance void [mscorlib]System.ArgumentOutOfRangeException::.ctor(string) 
    IL_001a: throw 
    IL_001b: ldarg.1 
    IL_001c: ldc.i4.1 
    IL_001d: add 
    IL_001e: starg.s input 
    IL_0020: ldarg.1 
    IL_0021: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_0026: nop 
    IL_0027: ret 
} // end of method Test::DoSomethingBrilliant 

y aquí es para la versión optimizada (donde se pone es malo):

.method public hidebysig instance void DoSomethingBrilliant(int32 input) cil managed 
{ 
    // Code size  31 (0x1f) 
    .maxstack 8 
    IL_0000: ldarg.1 
    IL_0001: ldc.i4  0x7fffffff 
    IL_0006: bne.un.s IL_0013 
    IL_0008: ldstr  "input" 
    IL_000d: newobj  instance void [mscorlib]System.ArgumentOutOfRangeException::.ctor(string) 
    IL_0012: throw 
    IL_0013: ldarg.1 
    IL_0014: ldc.i4.1 
    IL_0015: add 
    IL_0016: starg.s input 
    IL_0018: ldarg.1 
    IL_0019: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_001e: ret 
} // end of method Test::DoSomethingBrilliant 

veo un montón de llamadas adicionales antes de la operación tiro, pero voy a ser honesto - no tengo ni idea de lo ¡ellas hacen!

Respuesta

8

¿O solo es un error en la función de análisis de código?

Parece que. No es terriblemente sorprendente, para ser honesto, lograr que este tipo de análisis de código sea perfecto es muy complicado.Dado que cualquier intparticular no puede ser mayor que int.MaxValue, >= y == son definitivamente equivalentes.

+0

El analizador de código, probablemente ve los operadores de desigualdad como tener más seriedad que la igualdad simple. Ciertamente trato de cortar tanto del universo de valores cuando hago controles de seguridad. – bluevector

+0

Me interesa saber por qué lo haría bien en un ensamblado de "depuración" no optimizado. – kmp

+0

@kmp: No me gustaría decirlo. Me pregunto si '==' está optimizado de alguna manera extraña. ¿Has mirado el IL en absoluto? –

1

ver estas fragmentos de código:

if (x == int.MaxValue) return; 
// x != int.MaxValue 

y

if (x >= int.MaxValue) return; 
// x < int.MaxValue 

y

// x < int.MaxValue 
// rewrite 
// x + 1 <= int.MaxValue 
x++; 
// x <= int.MaxValue 

la poscondición de x ++ muestra (por derivación) que la condición previa tiene que ser:

x < int.MaxValue 

que sólo puede ser establecido en caso de que compruebe:

x >= int.MaxValue 
Cuestiones relacionadas