如果一個應用程式正在占用(「霸占」)所有處理器的注意力,其他程序最終會因「資源不足」而無法執行。
使用下列程式修正此類型的 Bug。
偵錯使用所有 CPU 週期的應用程式
找出造成此問題的應用程式: 使用 任務管理員 或 Perfmon 來查找使用了 99%% 或 100%% 處理器週期的進程。 這可能也會告訴您違規線程。
將 WinDbg、KD 或 CDB 附加至此程式。
找出造成問題的線程: 闖入違規的應用程式。 使用 !runaway 3 擴充功能來拍攝 CPU 時間去向的「快照」。 使用 g (Go) 並等候幾秒鐘。 然後再次闖入並使用 !runaway 3 。
0:002> !runaway 3 User Mode Time Thread Time 4e0 0:12:16.0312 268 0:00:00.0000 22c 0:00:00.0000 Kernel Mode Time Thread Time 4e0 0:00:05.0312 268 0:00:00.0000 22c 0:00:00.0000 0:002> g 0:001> !runaway 3 User Mode Time Thread Time 4e0 0:12:37.0609 3d4 0:00:00.0000 22c 0:00:00.0000 Kernel Mode Time Thread Time 4e0 0:00:07.0421 3d4 0:00:00.0000 22c 0:00:00.0000比較兩組數字,尋找使用者模式時間或核心模式時間增加最多的線程。 因為 !runaway 會依遞減的CPU時間排序,因此冒犯線程通常是清單頂端的線程。 在此情況下,線程0x4E0會造成問題。
使用 ~ (線程狀態) 和 ~s (設定目前線程) 命令,使這個成為目前的線程:
0:001> ~ 0 Id: 3f4.3d4 Suspend: 1 Teb: 7ffde000 Unfrozen . 1 Id: 3f4.22c Suspend: 1 Teb: 7ffdd000 Unfrozen 2 Id: 3f4.4e0 Suspend: 1 Teb: 7ffdc000 Unfrozen 0:001> ~2s使用 kb(顯示堆疊回溯) 來取得此線程的堆疊追蹤:
0:002> kb FramePtr RetAddr Param1 Param2 Param3 Function Name 0b4ffc74 77f6c600 000000c8.00000000 77fa5ad0 BuggyProgram!CreateMsgFile+0x1b 0b4ffce4 01836060 0184f440 00000001 0b4ffe20 BuggyProgram!OpenDestFileStream+0xb3 0b4ffd20 01843eba 02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3 0b4ffe20 01855924 0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4 0b4ffe5c 77e112e6 01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34 0b4ffeb0 77e11215 0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0 0b4ffed0 77e1a3b1 0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41 0b4fff40 77e181e4 02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b 0b4fff60 77e1a5df 02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91 0b4fff90 77e1ac1c 77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76在目前執行之函式的傳回位址上設定斷點。 在此情況下,傳回位址會顯示在第一行,如0x77F6C600。 傳回位址等同於第二行顯示的函式位移(BuggyProgram!OpenDestFileStream+0xB3)。 如果應用程式沒有可用的符號,則可能不會顯示函式名稱。 使用 g (Go) 命令來執行,直到到達此傳回地址為止,請使用符號或十六進位位址:
0:002> g BuggyProgram!OpenDestFileStream+0xb3如果觸發此斷點,請重複此過程。 例如,假設此斷點被觸發。 應採取下列步驟:
0:002> kb FramePtr RetAddr Param1 Param2 Param3 Function Name 0b4ffce4 01836060 0184f440 00000001 0b4ffe20 BuggyProgram!OpenDestFileStream+0xb3 0b4ffd20 01843eba 02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3 0b4ffe20 01855924 0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4 0b4ffe5c 77e112e6 01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34 0b4ffeb0 77e11215 0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0 0b4ffed0 77e1a3b1 0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41 0b4fff40 77e181e4 02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b 0b4fff60 77e1a5df 02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91 0b4fff90 77e1ac1c 77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76 0:002> g BuggyProgram!SaveMsgToDestFolder+0xb3如果達到此結果,請繼續執行:
0:002> kb FramePtr RetAddr Param1 Param2 Param3 Function Name 0b4ffd20 01843eba 02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3 0b4ffe20 01855924 0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4 0b4ffe5c 77e112e6 01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34 0b4ffeb0 77e11215 0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0 0b4ffed0 77e1a3b1 0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41 0b4fff40 77e181e4 02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b 0b4fff60 77e1a5df 02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91 0b4fff90 77e1ac1c 77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76 0:002> g BuggyProgram!DispatchToConn+0xa4最後,您會發現一個未被觸發的斷點。 在此情況下,您應該假設最後 一個 g 命令會設定執行的目標,而且不會中斷。 這表示 SaveMsgToDestFolder() 函式永遠不會傳回。
再次進入執行緒,並使用 bp(Set Breakpoint) 命令在 BuggyProgram!SaveMsgToDestFolder+0xB3 設置斷點。 然後重複使用 g 命令。 如果此斷點立即觸發,不論您執行目標程式多少次,您很可能已經識別出有問題的函式:
0:002> bp BuggyProgram!SaveMsgToDestFolder+0xb3 0:002> g 0:002> g使用 p (Step) 命令繼續執行 函式,直到您識別指令循環順序的位置為止。 然後,您可以分析應用程式的原始程式碼,以識別旋轉線程的原因。 原因通常會在 while、 do-while、 goto 或 for 循環的邏輯中發生問題。