当我们用CTRL + Break打破时,如何在WinDbg中看到真正的调用堆栈

时间:2017-06-05 17:26:34

标签: c++ multithreading debugging windows-7 windbg

当我们有一个常规断点时,调试器就会中断,我们会看到调用堆栈。但是如果我们使用CTRL + Break打破执行呢?我希望当前正在运行的线程可能会破坏whererbrt,但我通常会看到以下内容:

 # ChildEBP RetAddr  
00 02b7fdc4 7762f216 ntdll!DbgBreakPoint
01 02b7fdf4 76c0336a ntdll!DbgUiRemoteBreakin+0x3c
02 02b7fe00 775c9902 kernel32!BaseThreadInitThunk+0xe
03 02b7fe40 775c98d5 ntdll!__RtlUserThreadStart+0x70
04 02b7fe58 00000000 ntdll!_RtlUserThreadStart+0x1b
*** WARNING: Unable to verify checksum for ThreadDemo.exe

但是如何获得被中断的当前线程的实际代码?

我正在运行一个如下所示的长循环,这需要一段时间,我希望它能在那里打破。

void Bank::Deposit(void* param)
{
    Bank * bank = (Bank *)param;

    char *who = (char*) bank->bankName;

    int i;
    printf("%s: begin deposite\n", who);
    for (i = 0; i < 1000000000; i++) {
        bank->balance = bank->balance + 1;
    }
    printf("%s: done\n", who);

    return;
}

在这种情况下,当它中断时,其他一个线程确实在此函数中断,但这是一个简单的演示。在真正的Windows应用程序中,当我有很多线程时,我怎么能知道应用程序在哪里停止了(以及它在做什么)?

2 个答案:

答案 0 :(得分:3)

目前没有正在运行的线程&#39;当你点击ctrl-c。零,一个或多个线程可能正在运行,因此调试器甚至不会尝试解决其中的问题。一个打破 - 它在自己的线程中打破。仅仅因为你有一个可能正在运行的单个线程(但不一定如此)并没有改变它。

但你可以得到你想要的东西。当你点击ctrl-c时,它会破坏调试器线程并停止所有其他线程。您可以通过键入以下内容列出所有线程及其callstack:

~*k

您也可以通过输入以下内容切换到另一个主题:

~Ns

其中N是要切换到的线程的ID。

一旦你设置了当前的线程&#39;对于你想要的那个,你可以输入k来列出它的callstack和其他特定于线程的命令。

编辑:

请参阅this获取一份体面的特定于windbg线程的命令列表

答案 1 :(得分:2)

Ctrl + C Ctrl + Break 时,调试器会处理该键盘事件。这意味着调试器的至少一个线程当时正在运行,而不是你的。找出以前运行的线程并不容易。

调试器将在您的应用程序中使用调用堆栈上的int 3指令注入新线程。该线程没有立即运行,它首先必须由操作系统调度才能运行。这需要上下文切换。

当达到int 3时,进程中的所有线程都将被挂起,并向调试器通知该异常。所以,在你按下一个键之间,当线程实际停止时,大约15毫秒到大约30毫秒之间的时间过去了。

但是,这没什么好担心的。鉴于人类平均反应时间为25毫秒,数百万条CPU指令介于观察之间,这使得您想要停止线程和实际停止。

正如Sean Cline在评论和Mike Vine的回答中已经提到的那样,其他线程仍然存在。您可以使用~列出它们,使用~*k显示它们的调用堆栈,或切换到~ &lt; thread&gt; {{1}的特定线程}。