13

そこで、C# で次のコードを書きました。

class Test
{
    int a;
    System.IO.StreamReader reader;

    public Test()
    {
        a = 5;
        reader = new System.IO.StreamReader(String.Empty);
    }
}

そして、ILのクラスのコンストラクターは次のようになります

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       33 (0x21)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  nop
  IL_0007:  nop
  IL_0008:  ldarg.0
  IL_0009:  ldc.i4.5
  IL_000a:  stfld      int32 Test2.Test::a
  IL_000f:  ldarg.0
  IL_0010:  ldsfld     string [mscorlib]System.String::Empty
  IL_0015:  newobj     instance void [mscorlib]System.IO.StreamReader::.ctor(string)
  IL_001a:  stfld      class [mscorlib]System.IO.StreamReader Test2.Test::reader
  IL_001f:  nop
  IL_0020:  ret
} // end of method Test::.ctor

3 つのnopコマンドがあります。(私が知っているように、これは操作なしを表します)。それらのコマンドの必要性は何ですか。の代わりにコマンドがまったくなかった場合の違いは何ですかnop

4

2 に答える 2

19

これらは、C# コンパイラがプログラムの .pdb ファイルを書き込むときに使用されます。これには、コードのファイル + 行番号情報を含むデバッグ情報が含まれています。INT 3デバッガーはこれを使用して、ブレークポイントを設定したときにプログラムの実行を停止する命令を挿入する必要があるマシン コードを見つけます。ジッターは、MSIL 内の Opcodes.Nop ごとに NOP マシン コード命令を発行します。

にブレークポイントを設定すると、最初の nop が使用されますpublic Test()。Auto/Locals/Watch デバッグ ウィンドウでthis変数が有効になるように、基本コンストラクター呼び出しのに挿入されることに注意してください。

2 番目の nop は、最初の { 中括弧にブレークポイントを設定するときに使用されます。その行はコードをまったく生成しないため、偽の MSIL 命令が必要です。

最後の } 中括弧に対して生成された 3 番目の nop についても同じ話です。そのブレークポイントにブレークポイントを設定すると、メソッドの戻り値 (存在する場合) を調べることができます。Debug + Windows + Registers ウィンドウで間接的に表示されます。VS2013 で改善されました。

したがって、これはプログラムのデバッグに役立つだけであり、ブレークポイントが予測どおりに動作します。これらの NOP は、プログラムのリリース構成を構築するときに生成されません。C# プロジェクトにデバッグ構成とリリース構成がある大きな理由の 1 つです。リリース ビルドをデバッグすることはできますが、それはあなたの正気を疑わせるかなり混乱した経験です :)

于 2013-10-06T13:41:22.663 に答える
3

これらは、デバッグ モードでビルドするときにブレークポイントをサポートするために使用され、アセンブリの実行に違いはありません。

于 2013-10-06T07:30:04.580 に答える