Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Se un'applicazione sta consumando ("hogging") tutta l'attenzione del processore, gli altri processi finiranno per "fame" e non potranno essere eseguiti.
Usare la procedura seguente per correggere un bug di questo tipo.
Debug di un'applicazione che usa tutti i cicli della CPU
Identificare l'applicazione che causa questo problema: Usare gestione attività o Perfmon per individuare il processo che usa 99% o 100% dei cicli del processore. Questo può indicare anche il thread incriminato.
Collegare WinDbg, KD o CDB a questo processo.
Identificare il thread che causa il problema: Interrompere l'applicazione che causa l'errore. Usare l'estensione !runaway 3 per creare uno "snapshot" del consumo di tempo CPU. Usare g (Go) e attendere alcuni secondi. Quindi effettuare un accesso e usare di nuovo !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.0000Confrontare i due set di numeri e cercare il thread il cui tempo in modalità utente o tempo in modalità kernel è aumentato di più. Poiché !runaway ordina per tempo di CPU decrescente, il thread che causa l'errore è in genere quello nella parte superiore dell'elenco. In questo caso, il thread 0x4E0 causa il problema.
Usare i comandi ~ (stato del thread) e ~s (imposta il thread corrente) per impostare questo come il thread corrente:
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> ~2sUsare kb (Display Stack Backtrace) per ottenere un'analisi dello stack di questo thread:
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+0x76Impostare un punto di interruzione sull'indirizzo di ritorno della funzione in esecuzione. In questo caso, l'indirizzo restituito viene visualizzato nella prima riga come 0x77F6C600. L'indirizzo restituito equivale all'offset della funzione mostrato nella seconda riga (BuggyProgram!OpenDestFileStream+0xB3). Se non sono disponibili simboli per l'applicazione, il nome della funzione potrebbe non essere visualizzato. Usare il comando g (Go) per eseguire fino a raggiungere questo indirizzo di ritorno, usando un indirizzo simbolico o esadecimale.
0:002> g BuggyProgram!OpenDestFileStream+0xb3Se questo punto di interruzione viene raggiunto, ripetere il processo. Si supponga, ad esempio, che questo punto di interruzione venga raggiunto. È necessario eseguire i passaggi seguenti:
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+0xb3Nel caso venga raggiunto, continuare con:
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+0xa4Infine si troverà un punto di interruzione che non viene raggiunto. In questo caso, è consigliabile presupporre che l'ultimo comando g abbia avviato la destinazione e che non si sia interrotta. Ciò significa che la funzione saveMsgToDestFolder() non verrà mai restituita.
Entrare di nuovo nel thread e impostare un punto di interruzione su BuggyProgram!SaveMsgToDestFolder+0xB3 con il comando bp (Imposta punto di interruzione). Usare quindi ripetutamente il comando g. Se questo punto di interruzione viene attivato immediatamente, indipendentemente dal numero di volte in cui hai eseguito il programma, è molto probabile che tu abbia identificato la funzione problematica.
0:002> bp BuggyProgram!SaveMsgToDestFolder+0xb3 0:002> g 0:002> gUtilizzare il comando p (passaggio) per procedere attraverso la funzione fino a identificare il punto in cui si trova la sequenza di istruzioni ciclica. È quindi possibile analizzare il codice sorgente dell'applicazione per identificare la causa del thread rotante. La causa in genere sarà un problema nella logica di un mentre, do-while, gotoo per il ciclo di.