Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Jeśli jedna aplikacja zawłaszcza całą uwagę procesora, inne procesy będą 'głodować' i nie będą w stanie działać.
Użyj poniższej procedury, aby poprawić usterkę tego rodzaju.
Debugowanie aplikacji korzystającej ze wszystkich cykli procesora CPU
Zidentyfikuj, która aplikacja powoduje ten problem: Użyj Menedżera zadań lub narzędzia Perfmon , aby znaleźć, który proces używa 99% lub 100% cykli procesora. Może to również wskazać problematyczny wątek.
Dołącz windbg, KD lub CDB do tego procesu.
Zidentyfikuj, który wątek powoduje problem: Włamaj się do aplikacji naruszającej dane. Użyj rozszerzenia !runaway 3, aby zrobić "migawkę" pokazującą, gdzie zużywany jest cały czas procesora. Użyj g (Go) i zaczekaj kilka sekund. Następnie przerwij i użyj !runaway 3 ponownie.
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.0000Porównaj dwa zestawy liczb i poszukaj wątku, którego czas trybu użytkownika lub czas trybu jądra wzrósł najbardziej. Ponieważ !runaway sortuje według malejącego czasu procesora CPU, wątek powodujący problem jest zwykle tym na szczycie listy. W tym przypadku wątek 0x4E0 powoduje problem.
Użyj poleceń ~ (stan wątku) i ~s (Ustaw bieżący wątek), aby wykonać ten bieżący wątek:
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> ~2sUżyj kb (Display Stack Backtrace), aby uzyskać ślad stosu tego wątku:
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+0x76Ustaw punkt przerwania na adres zwrotny aktualnie uruchomionej funkcji. W takim przypadku adres zwrotny jest wyświetlany w pierwszym wierszu jako 0x77F6C600. Adres zwrotny jest równoważny przesunięciu funkcji wyświetlanemu w drugim wierszu (BuggyProgram!OpenDestFileStream+0xB3). Jeśli dla aplikacji nie są dostępne żadne symbole, nazwa funkcji może nie być widoczna. Użyj polecenia g (Go), aby wykonać polecenie do momentu osiągnięcia tego adresu zwrotnego przy użyciu adresu symbolicznego lub szesnastkowego:
0:002> g BuggyProgram!OpenDestFileStream+0xb3Jeśli ten punkt przerwania zostanie trafiony, powtórz proces. Załóżmy na przykład, że ten punkt przerwania został trafiony. Należy wykonać następujące czynności:
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+0xb3Jeśli zostanie to trafione, kontynuuj wykonywanie następujących czynności:
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+0xa4Na koniec znajdziesz punkt przerwania, który nie zostanie aktywowany. W tym przypadku należy założyć, że ostatnie polecenie g uruchomiło docelowy element i nie zostało przerwane. Oznacza to, że funkcja SaveMsgToDestFolder() nigdy nie zwróci.
Ponownie włamaj się do wątku i ustaw punkt przerwania w BuggyProgram! SaveMsgToDestFolder+0xB3 za pomocą polecenia bp (Ustaw punkt przerwania). Następnie użyj polecenia g wielokrotnie. Jeśli ten punkt przerwania trafi natychmiast, niezależnie od tego, ile razy wykonano cel, jest bardzo prawdopodobne, że zidentyfikowano funkcję powodującą problem:
0:002> bp BuggyProgram!SaveMsgToDestFolder+0xb3 0:002> g 0:002> gUżyj polecenia p (Krok), aby przejść przez funkcję do momentu zidentyfikowania miejsca, w którym znajdują się sekwencja pętli instrukcji. Następnie możesz przeanalizować kod źródłowy aplikacji, aby zidentyfikować przyczynę wirującego wątku. Przyczyna zwykle okaże się problemem w logice while, do-while, goto lub for pętli.