c# - CIL中的nop有什么意义

标签 c# cil

所以我用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

会有什么不同

最佳答案

C# 编译器在为您的程序编写 .pdb 文件时使用它们。其中包含调试信息,其中包括代码的文件+行号信息。调试器使用它来查找需要注入(inject) INT 3 指令以使程序在您设置断点时停止执行的机器代码。抖动为 MSIL 中的每个 Opcodes.Nop 发出一条 NOP 机器码指令。

当您在 public Test() 上设置断点时,将使用第一个 nop。请注意,它是在基础构造函数调用之后注入(inject)的,因此this变量在自动/本地/监视调试窗口中变得有效。

当您在第一个 { 花括号上设置断点时,将使用第二个 nop。该行根本不生成任何代码,因此非常需要伪造的 MSIL 指令。

第三个 nop 的故事相同,为最后一个 } 大括号生成。当您在该断点上设置断点时,您可以检查方法返回值(如果有)。在 Debug + Windows + Registers 窗口中间接可见。在 VS2013 中得到改进。

所以这只是帮助调试您的程序,它们使断点的行为可预测。当您构建程序的发布配置时,这些 NOP 不会生成。 C# 项目具有调试和发布配置的一个重要原因。您仍然可以调试 Release 版本,但是这是一种令人困惑的体验,让您怀疑自己的理智 :)

关于c# - CIL中的nop有什么意义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19206428/

相关文章:

c# - 4.0 .NET Framework 中的所有通用集合/类型是什么?

c# - Identity Manager w/ASP.NET Identity HostSecurityConfiguration 登录

c# - CIL类和方法的命名规则是什么

c# - 显式空检查与空合并运算符的编译器评估?

.net - 在实现接口(interface)但使用基类的成员实现的 .NET 中创建 DynamicType

c# - "Could not find a part of the path"错误信息

c# - 如何在打印 PDF 时设置打印机设置

c# - 显示来自不同 Controller 的操作 View

static-analysis - 使用静态字节码分析来确定通过给定方法的所有可能路径是否是尝试解决停机问题的变体?

c# - 终于理解try catch的MSIL