代码之家  ›  专栏  ›  技术社区  ›  Mike Dinescu

调试.NET CLR应用程序时,如何查看评估堆栈上的局部变量?

  •  4
  • Mike Dinescu  · 技术社区  · 16 年前

    我正在使用windbg(具有sos扩展名)并尝试调试崩溃的应用程序。我可以转储引发异常的调用的IL,通过检查代码,如果可以转储评估堆栈的内容,我似乎可以获得所需的信息。有没有可能用windbg&sos做什么?

    我是这样做的:

    1. 开始风车
    2. 附加到崩溃进程
    3. 由SoS mscorwks加载 (加载SoS扩展)
    4. !令牌2EE 兆字节 0600 000 9A (何处) 兆字节 是应用程序(和程序集)的名称t 我要戴的帽子 9A 是由Windows错误报告工具报告的崩溃方法的方法偏移量 . 我得到这个输出:

      模块:000e2c3c(applicationname.exe)
      令牌:0x060009A
      方法描述:000E67C8
      名称:mynamespace.myclassname.theculpritfn(myotherclass)
      jitted代码地址:0081B1D0

    5. !DUMPIL 0E667 C8 (为所讨论的方法而丢弃了IL) . 这是输出:

      
      // ..
      // .. the previous code omitted for brevity
      .catch
      {
       IL_0071: stloc.0
       IL_0072: nop
       IL_0073: ldstr "Can't set CurrentServer property for: "
       IL_0078: ldarg.0
       IL_0079: ldfld MyNamespace.MyClassName::_currentServer
       IL_007e: brtrue.s IL_0087
       IL_0080: ldstr ""
       IL_0085: br.s IL_0092
       IL_0087: ldarg.0
       IL_0088: ldfld MyNamespace.MyClassName::_currentServer
       IL_008d: callvirt MyNamespace.MyOtherClass::get_Name
       IL_0092: call System.String::Concat
       IL_0097: ldloc.0
       IL_0098: newobj MyNamespace.MySpecialExceptionType::ctor
       IL_009d: throw
      } 
      

      问题是:有没有一种方法可以让我看到在抛出异常之前在堆栈上推送了什么。如果我没有弄错,传入异常构造函数的参数应该是评估堆栈索引0处的局部变量。

      P.S.我打电话的时候 !CLSRADES-A 我收到消息说: 无法遍历托管堆栈。当前线程可能不是托管线程。你可以跑!获取进程中托管线程列表的线程。

    谢谢!

    2 回复  |  直到 16 年前
        1
  •  4
  •   Brian Rasmussen    16 年前

    您需要识别并选择正确的线程。当前线程的ID显示在windbg提示中。

    !threads 将显示应用程序中的所有托管线程。一旦确定,可以使用 ~Xs 其中x是线程的windbg id。

    !clrstack 将显示堆栈跟踪。如果需要局部变量和/或参数,请使用 -l / -p (或) -a 两者兼而有之。

    您可以遍历所有线程并列出它们的调用堆栈 ~*e!clrstack .

    如果本地/参数不能满足您的需要,请使用 !dso 显示推到堆栈上的对象。

        2
  •  1
  •   AaronBa    16 年前

    哇,这很难,没有一个真正的垃圾戳穿。-)

    这里有几个问题……然后我将添加一个在上面的答案中没有列出的命令。

    问题:

    1. 您确定要捕获的是第一个异常,而不是最后一个未处理的异常,并破坏了进程吗?

    2. 您能看看抛出异常的线程的本机调用堆栈吗?
      注意:应该存在对raiseException()的调用或访问冲突。

    3. 注意异步异常,这些异常与您的代码完全无关,并且可能会将您带入一个catch块中…或更糟(thread.abortException/system.outofmemoryException和…StackOverflowException:-)

    继续前进 !堆栈 在断层线上。输出是 不精确 然而,它确实在线程调用堆栈中执行了一项惊人的工作,您可能会很幸运地看到 @ 在消息中引用.cxr和.exr异常的符号。如果你这样做了,你就可以跑了 .cxr-cxr地址 看看异常链中的第一个异常是什么。

    要点:尽管我可能是站在一边提出问题,但如果调用了异常, 未处理 并取下您可能希望记录初始调用堆栈的进程,或者将前一个异常添加为内部异常,以便确定根本原因。

    谢谢, 亚伦