当我们有一个常规断点时,调试器就会中断,我们会看到调用堆栈。但是如果我们使用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应用程序中,当我有很多线程时,我怎么能知道应用程序在哪里停止了(以及它在做什么)?
答案 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}的特定线程}。