2012-06-27 8 views
13

Sto usando Visual Studio 2010 SP1 finale su AC# progetto di libreria di classi (.net 4) e sono curioso di sapere qualcosa ...Perché dovrei controllare per maggiore di Int32.MaxValue?

Dato questo metodo:

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

    input++; 

    Console.WriteLine(input); 
} 

ottengo questo avvertimento da parte analisi del codice:

CA2233: Microsoft.Usage: correggere la potenziale overflow 'ingresso + 1' l'operazione 'Test.DoSomethingBrilliant (int)'.

ho pensato a me, che è un po 'strano dal momento che sto controllando che l'operazione non sarà in overflow input++ lanciando tale eccezione sgargianti all'inizio, ma ho cambiato a questo:

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

    input++; 

    Console.WriteLine(input); 
} 

e sicuramente l'avviso è andato via.

Ora il mio piccolo cervello è tutto confuso perché dato che sto ottenendo un argomento int perché il controllo per vedere se è maggiore del valore massimo consentito per un intero fornisce mai alcun valore?

Quindi sono tornato al bit originale del codice e sono passato al debug e l'ho creato senza avvertimento! Curiouser e curioser ...

ho controllato le differenze tra il debug e rilascio e scoperto che se ho spuntare il codice Ottimizzare opzione avvertimento da analisi del codice apre right back up.

Quindi l'ottimizzazione si traduce in qualcosa che significa che è necessario controllare maggiore di int.MaxValue. Eh? Perché? Sono super denso? Cosa ha fatto l'ottimizzazione che significa che potrei ottenere un int più grande di int.MaxValue passato in un metodo che accetta un int?

Oppure, questo è solo un bug nella funzionalità di analisi del codice?

Aggiornamento

Ecco l'IL per la versione "non ottimizzata" (dove l'analisi del codice ottiene di destra):

.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 

e qui è per la versione ottimizzata (dove ottiene sbagliato):

.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 

vedo un sacco di chiamate in più prima dell'operazione tiro, ma ho intenzione di essere onesto - non ho idea di che cosa loro fanno!

risposta

8

Oppure, questo è solo un bug nella funzionalità di analisi del codice?

Sembra. Non è terribilmente sorprendente, ad essere onesti, ottenere questo tipo di analisi del codice per essere perfetto è molto difficile.Dato che qualsiasi particolare intnon può essere superiore a int.MaxValue, >= e == sono decisamente equivalenti.

+0

L'analizzatore di codice vede probabilmente gli operatori di disuguaglianza come avere più gravitas di semplice uguaglianza. Cerco certamente di ridurre gran parte dell'universo dei valori quando eseguo i controlli di sicurezza. – bluevector

+0

Sono interessato perché lo farebbe correttamente su un assembly "debug" non ottimizzato? – kmp

+0

@kmp: non vorrei dire. Mi chiedo se '==' sia ottimizzato in qualche modo strano. Hai mai visto l'IL? –

1

Vedi questi frammenti di codice:

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

e

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

e

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

postcondizione di x ++ spettacoli (di derivazione) che la condizione deve essere:

x < int.MaxValue 

che può essere stabilito solo in caso di controllare:

x >= int.MaxValue 
Problemi correlati