Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在匿名方法中断开WinDbg?_C#_Debugging_Windbg_Anonymous Methods_Sos - Fatal编程技术网

C# 如何在匿名方法中断开WinDbg?

C# 如何在匿名方法中断开WinDbg?,c#,debugging,windbg,anonymous-methods,sos,C#,Debugging,Windbg,Anonymous Methods,Sos,标题说明了一切。通常的SOS命令!bpmd没有名字就没有什么好处 我有一些想法: 转储所有方法,然后使用!bpmd-md当您找到相应的MethodDesc时 据我所知,在现实世界中并不实用。即使我编写了一个宏来将转储限制为匿名类型/方法,也没有明显的方法来区分它们 使用Reflector转储MSIL名称 在处理动态程序集和/或Reflection.Emit时没有帮助。Visual Studio无法读取此类场景中的本地变量,这就是我首先转向Windbg的全部原因 在VS中设置断点,等待它

标题说明了一切。通常的SOS命令!bpmd没有名字就没有什么好处

我有一些想法:

  • 转储所有方法,然后使用!bpmd-md当您找到相应的MethodDesc时
    • 据我所知,在现实世界中并不实用。即使我编写了一个宏来将转储限制为匿名类型/方法,也没有明显的方法来区分它们
  • 使用Reflector转储MSIL名称
    • 在处理动态程序集和/或Reflection.Emit时没有帮助。Visual Studio无法读取此类场景中的本地变量,这就是我首先转向Windbg的全部原因
  • 在VS中设置断点,等待它命中,然后
    • 尝试从VS分离会导致其挂起(与应用程序一起挂起)。我认为这是因为托管调试器是一个标准调试器,而不是一个标准的“硬”调试器。或者它只是Silverlight特有的一个VS bug(可能不是第一个)
  • 在其他已知的位置设置断点以调用匿名方法,然后单步执行
    • 我的备份计划,但如果这个问答揭示了一个更好的方法,我宁愿不求助于它

    • 匿名方法并不是真正的匿名方法。它只是隐藏在编译器生成的名称后面

      考虑这个小例子:

      Func<int, int> a = (x) => x + 1;
      
      Console.WriteLine(a.Invoke(1));
      
      通过MethodDesc,我们可以为
      Main()

      0:000>!dumpil 00163010
      ilAddr=003f2068
      IL_0000:没有
      IL_0001:ldstr“按回车键”
      IL_0006:呼叫系统控制台::WriteLine
      没有
      IL_000c:呼叫系统控制台::ReadLine
      IL_0011:流行音乐
      IL_0012:ldsfld TestBench.Program::CS$9_ucachedanonymousmethoddelegate1
      IL_0017:brtrue.s IL_002c
      IL_0019:ldnull
      IL_001a:ldftn测试台。程序::b_u0
      IL_0020:newobj类[System.Core]System.Func`2::.ctor
      IL_0025:stsfld TestBench.Program::CS$9_ucachedanonymousmethoddelegate1
      IL_002a:br.s IL_002c
      IL_002c:ldsfld测试台。程序::CS$9_缓存匿名方法delegate1
      IL_0031:stloc.0
      IL_0032:ldloc.0
      IL_0033:ldc.i4.1
      IL_0034:callvirt类[System.Core]System.Func`2::Invoke
      IL_0039:呼叫系统控制台::WriteLine
      IL_003e:没有
      IL_003f:ret
      
      注意那些有趣的名字。它们是生成委托类型和实际方法的名称。该方法称为
      b_uu0
      。让我们看看这个方法:

      0:000> !name2ee * TestBench.Program.<Main>b__0
      Module: 6db11000 (mscorlib.dll)
      --------------------------------------
      Module: 00152c5c (TestBench.exe)
      Token: 0x06000003
      MethodDesc: 00153024
      Name: TestBench.Program.<Main>b__0(Int32)
      Not JITTED yet. Use !bpmd -md 00153024 to break on run. 
      
      0:000>!名称2ee*TestBench.Program.b_u\u 0
      模块:6db11000(mscorlib.dll)
      --------------------------------------
      模块:00152c5c(TestBench.exe)
      令牌:0x06000003
      方法描述:00153024
      名称:TestBench.Program.b___0(Int32)
      还没有紧张。使用!bpmd-md 00153024在运行时中断。
      
      给你。MethodDesc是00153024,正如评论所说,您可以使用!bpmd使用MethodDesc设置断点

      如果在您的场景中查找“…”名称很棘手,那么将其作为常规方法如何?这通常非常简单;唯一棘手的事情是捕获变量,但这并不太糟糕——例如,这些变量做同样的事情:

          static void Main()
          {
              List<int> list = new List<int> { 1, 2, 3, 4, 5 };
              int div = 2;
              foreach (var item in list.Where(x => x % div == 0))
              {
                  Console.WriteLine(item);
              }
      
              ListSearcher ls = new ListSearcher();
              ls.div = 2;
              foreach (var item in list.Where(ls.Test))
              {
                  Console.WriteLine(item);
              }
          }
          class ListSearcher
          {
              public int div;
              public bool Test(int x)
              {
                  return x % div == 0;
              }
          }
      
      static void Main()
      {
      列表=新列表{1,2,3,4,5};
      int div=2;
      foreach(列表中的变量项,其中(x=>x%div==0))
      {
      控制台写入线(项目);
      }
      ListSearcher ls=新ListSearcher();
      ls.div=2;
      foreach(列表中的var项目,其中(ls.测试))
      {
      控制台写入线(项目);
      }
      }
      类列表搜索器
      {
      公共情报处;
      公共布尔测试(int x)
      {
      返回x%div==0;
      }
      }
      
      转储操作指向的方法描述符。方向。

      Nota bene:我意外发现WinDbg不必要了。如果您在动态程序集创建期间以编程方式发出DebuggableAttribute(),您将能够在VisualStudio中很好地看到本地变量。
      0:000> !name2ee * TestBench.Program.<Main>b__0
      Module: 6db11000 (mscorlib.dll)
      --------------------------------------
      Module: 00152c5c (TestBench.exe)
      Token: 0x06000003
      MethodDesc: 00153024
      Name: TestBench.Program.<Main>b__0(Int32)
      Not JITTED yet. Use !bpmd -md 00153024 to break on run. 
      
          static void Main()
          {
              List<int> list = new List<int> { 1, 2, 3, 4, 5 };
              int div = 2;
              foreach (var item in list.Where(x => x % div == 0))
              {
                  Console.WriteLine(item);
              }
      
              ListSearcher ls = new ListSearcher();
              ls.div = 2;
              foreach (var item in list.Where(ls.Test))
              {
                  Console.WriteLine(item);
              }
          }
          class ListSearcher
          {
              public int div;
              public bool Test(int x)
              {
                  return x % div == 0;
              }
          }