2013-10-06 11 views
12

だから、私はC#で次のコードを書いた。CILのnopのポイント

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

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

そしてIL内のクラスのコンストラクタは3つのnopコマンドがあります。この

.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 

のように見えます。 (私が知っているように、何の操作もない)。これらのコマンドの必要性は何ですか? nop

答えて

16

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

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

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

最後の}中かっこのために生成された3番目のnopの同じストーリー。その上にブレークポイントを設定すると、メソッドの戻り値(もしあれば)を調べることができます。 Debug + Windows + Registersウィンドウで間接的に表示されます。 VS2013で改善されました。

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

3

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

関連する問題