2017-06-05 41 views
0

當我們有一個常規的斷點時,調試器會在那裏出現,然後我們看到調用堆棧。但是如果我們使用CTRL + Break來中斷執行呢?我希望當前運行的線程打破whererbrt它,但我所看到的通常是這樣的:如何在CTRL + Break的情況下查看WinDbg中的實際調用堆棧

# 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

正如你所發現的那樣,從調試器入手的過程會產生一個獨立的線程來完成中斷。要查看* all *線程的堆棧跟蹤,請使用['〜* kv'](https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/---thread-status-)。當您看到正在運行您想要調查的代碼的線程ID時,請使用['〜0s'](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-s --set-current-thread-),假設0是線程ID,將其設置爲當前線程。 –

回答

2

當你按下按Ctrl + ç按Ctrl + ,由處理該鍵盤事件調試器。這意味着調試器的至少一個線程當時正在運行,而不是您的。搞清楚哪個線程以前運行並不容易。

調試器會在調用堆棧上使用int 3指令將新線程注入到應用程序中。此線程不是立即運行,它首先必須由操作系統安排運行。這需要上下文切換。

當達到int 3時,進程中的所有線程都會掛起,調試器會收到有關異常的通知。所以,在你按下一個鍵之間,當線程實際停止時,經過〜15 ms和〜30 ms之間的時間。

但是,這沒有什麼可擔心的。考慮到人類平均反應時間爲25毫秒,數百萬條CPU指令位於您想要停止線程和實際停止的觀察之間。

正如Sean Cline在評論和Mike Vine的回答中所提到的,其他線程在那裏仍然存在。你可以用~一一列舉,使用~*k或切換到一個特定的線程與~<線程>s顯示他們的調用堆棧。

3

當你點擊ctrl-c時,沒有'正在運行的當前線程'。零,一個或多個線程可能正在運行,所以調試器甚至不會嘗試解決'哪個'破壞 - 它會在自己的線程中斷開。僅僅因爲你有一個可能正在運行的單線程(但不一定是這樣)不會改變它。

但你可以得到你想要的。當你點擊ctrl-c時,它會打破調試器線程並停止所有其他線程。您可以通過鍵入列出所有線程和它們的調用堆棧:

~*k

您還可以開關到另一個線程通過鍵入:

~Ns

其中N是線程的ID切換到。

將當前線程設置爲您想要的那個之後,您可以鍵入k以列出其調用堆棧和其他線程特定的命令。

編輯:

看到this的WinDbg的線程體面的列表中選擇特定的命令

相關問題