【问题标题】:How to see my programs stack trace?如何查看我的程序堆栈跟踪?
【发布时间】:2014-08-27 23:20:33
【问题描述】:

我正在努力学习 WinDbg。在简单的程序中,我无限等待Critical Section。我的程序挂起,我使用任务管理器得到程序的转储。

现在,每当我使用 kck 命令获取堆栈跟踪时,它都会给我以下堆栈跟踪。

wow64cpu!CpupSyscallStub
wow64cpu!Thunk0ArgReloadState
wow64!RunCpuSimulation
wow64!Wow64LdrpInitialize
ntdll!LdrpInitializeProcess
ntdll!_LdrpInitialize
ntdll!LdrInitializeThunk

现在,为什么它不显示我的实际代码的堆栈跟踪。我如何理解我的程序究竟挂在哪里?

【问题讨论】:

  • 也许你正在转储错误的线程堆栈?你试过~*k吗?
  • 使用 ProcessExplorer 捕获 dmp 并在 Windbg 中运行 !analyze -v -hang
  • 如果您使用 64 位版本的任务管理器生成转储,您将获得 32 位模拟器 (wow64*) 的转储。使用 32 位版本的任务管理器生成 32 位进程的故障转储。
  • @joshpoley ProcessExplorer 生成具有正确位数的转储,因此您无需关心这一点。
  • @magicandre1981 可以使用 -hang。谢谢。

标签: windows debugging windbg dump freeze


【解决方案1】:

以前关于捕获 32 位转储的答案都可以。但是,如果您没有机会创建另一个转储(例如,如果问题难以重现),请尝试 WOW64 扩展:

0:000> k
Child-SP          RetAddr           Call Site
00000000`0008e2e8 00000000`7449aeac wow64win!NtUserGetMessage+0xa
...
00000000`0008f7d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe

0:000> .load wow64exts

0:000> !sw
Switched to 32bit mode

0:000:x86> k
ChildEBP RetAddr  
00141568 755f790d user32!NtUserGetMessage+0x15
00141584 004aa378 user32!GetMessageW+0x33
00141634 00400000 notepad__+0xaa378
...

注意输入提示如何更改为0:000:x86>,并且调用堆栈正确显示。

虽然!sw 向前和向后切换,但您也可以使用.effmach x86.effmach amd64 更具体。

【讨论】:

    【解决方案2】:

    请使用ProcessExplorer 捕获dmp。从版本 15.13 开始,它会生成 dumps with the correct bitness

    它还会创建与目标位数匹配的转储文件 进程

    现在打开适合位数的 Windbg.exe 中的转储并运行!analyze -v -hang

    -hang 告诉命令进行挂起分析。这应该会向您显示您遇到问题的代码部分。

    【讨论】:

      【解决方案3】:

      您的程序是在 64 位 Windows 上运行的 32 位应用程序。您应该使用 32 位 WinDbg 来调试它。在典型的 Windows SDK 安装中,它将位于 C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\windbg.exe

      【讨论】:

      • 我得到与 WinDbg{x86) 完全相同的输出。
      【解决方案4】:

      欢迎来到 Windbg 的世界。与具有出色 GUI 的现代调试器不同,Windbg 更多地基于命令行,因此可能具有更陡峭的学习曲线。但是一旦你掌握了它 - 它就很棒!

      关于你的问题:

      Lieven 已经给出了提示。我会详细说明一下。

      您编写的示例应用程序中可能运行了多个线程。

      ~ 将给出所有线程的列表。

      ~* k 将转储所有线程的堆栈。

      接下来,您可以使用

      移动到您希望调试的线程

      ~ <thread ID>s

      This 是在 Windbg 中开始使用不同命令的绝佳资源。

      【讨论】:

        【解决方案5】:

        使用!analyze -hang!locks¬cs -s -o -l 查看是否出现死锁情况。后者是我更喜欢的。

        至于为什么当你打开转储时它显示一个不相关的线程调用堆栈,当你创建转储时你的程序可能处于任何事情的中间,并不总是感兴趣的线程是你需要做一些事情的原因分析。

        !locks 的输出中,它将转储所有被锁定的关键部分,您要查找的是 2 个 threadId 正在等待彼此资源的位置,然后使用 ~~[TID]s kb 切换到这些线程以转储调用stack 然后查找ntdll!RtlEnterCriticalSectionfunction,第一个参数将是它正在等待的临界区的地址,你应该发现你的2个线程正在等待彼此的临界区。然后,您需要查看您的代码并了解您的锁定机制是否存在缺陷。

        【讨论】:

        • 据我了解这不是死锁情况,这是一个无限超时的简单等待。
        • @ThomasW。 OP 在 cmets 中提到 !analyze -hang 为他工作,所以我认为这是一个僵局
        猜你喜欢
        • 1970-01-01
        • 2011-05-18
        • 1970-01-01
        • 1970-01-01
        • 2017-08-26
        • 2015-10-03
        • 2012-05-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多