为什么我需要检查大于Int32.MaxValue?

时间:2012-06-27 12:23:50

标签: c# .net

我在c#类库项目(.net 4)上使用Visual Studio 2010 SP1 Ultimate,我很好奇......

鉴于此方法:

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

    input++;

    Console.WriteLine(input);
}

我从代码分析中得到了这个警告:

  
    

CA2233:Microsoft.Usage:纠正'Test.DoSomethingBrilliant(int)'中'input + 1'操作中的潜在溢出。

  

我心里想,这有点奇怪,因为我检查input++操作不会因为在开始时抛出那个时髦的异常而溢出,但我把它更改为:

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

    input++;

    Console.WriteLine(input);
}

果然警告消失了。

现在我的小脑子都很困惑,因为我得到一个int作为参数,为什么要检查它是否大于允许整数提供任何值的最大值?

然后我回到原来的代码并切换到调试,它没有警告就构建了! Curiouser和curioser ......

我检查了调试和发布之间的差异,发现如果我勾选优化代码选项,代码分析的警告会立即弹回。

因此,优化会导致我需要检查的内容大于int.MaxValue。咦?为什么?我超级密集吗?进行了哪些优化意味着我可能会在接受int.MaxValue的方法中获得大于int的int?

或者,这只是代码分析功能中的一个错误吗?

更新

这是“未经优化”版本的IL(代码分析正确):

.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

这里是优化版本(它出错了):

.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

我在投掷操作之前看到了一堆额外的调用,但我会说实话 - 我不知道他们做了什么!

2 个答案:

答案 0 :(得分:7)

  

或者,这只是代码分析功能中的一个错误吗?

看起来像。说实话非常令人惊讶 - 让这种代码分析变得完美是非常棘手的。鉴于任何特定的int 不能大于int.MaxValue>===肯定是等效的。

答案 1 :(得分:1)

请参阅以下代码片段:

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

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

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

x ++的后置条件显示(通过推导) 前提条件必须是:

x < int.MaxValue 

只有在您检查时才能建立:

x >= int.MaxValue
相关问题