13

ac#クラスライブラリプロジェクト(.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を取得しているので、整数に許可されている最大値よりも大きいかどうかを確認するために、なぜ私の小さな頭脳はすべて混乱していますか?

次に、元のコードに戻り、デバッグに切り替えました。警告なしでビルドされました。好奇心旺盛で好奇心旺盛な...

デバッグとリリースの違いを確認したところ、 [コードの最適化]オプションにチェックマークを付けると、コード分析からの警告がすぐに表示されることがわかりました。

したがって、最適化の結果、 int.MaxValueより大きいかどうかを確認する必要があることを意味します。は?なんで?私は超高密度ですか?intを受け入れるメソッドに渡されるint.MaxValueよりも大きい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

スロー操作の前にたくさんの余分な呼び出しが表示されますが、正直に言うと、それらが何をするのかわかりません。

4

2 に答える 2

7

または、これはコード分析機能の単なるバグですか?

そのように見える。正直なところ、それほど驚くことではありません。この種のコード分析を完璧にするのは非常に難しいことです。特定のものを大きくint することはできずint.MaxValue、間違いなく同等です。>===

于 2012-06-27T12:28:36.540 に答える
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
于 2015-01-25T10:56:31.183 に答える