Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Med TTD (Time Travel Debugging) kan användare registrera spårningar, som är inspelningar av körningen av ett program. Tidslinjer är en visuell framställning av händelser som inträffar under utförandet. Dessa händelser kan vara platser för brytpunkter, minnesläsning/skrivningar, funktionsanrop och returer samt undantag.
Använd fönstret Tidslinjer för att visa viktiga händelser, förstå deras relativa position och enkelt gå till deras plats i TTD-spårningsfilen. Använd flera tidslinjer för att visuellt utforska händelser i tidsresespårningen och identifiera händelsekorrelation.
Fönstret Tidslinjer visas när du öppnar en TTD-spårningsfil. Den visar viktiga händelser utan att du behöver skapa datamodellfrågor manuellt. Samtidigt är alla tidsreseobjekt tillgängliga för att möjliggöra mer komplexa datafrågor.
Mer information om hur du skapar och arbetar med spårningsfiler för tidsresor finns i Felsökning av tidsresor: Översikt.
Typer av tidslinjer
Fönstret Tidslinjer visar händelser i följande tidslinjer:
- Undantag: Du kan filtrera på en specifik undantagskod.
- Brytpunkter: Du kan se när brytpunkter träffar på en tidslinje.
- Minnesåtkomst: Du kan läsa, skriva och köra mellan två minnesadresser.
-
Funktionsanrop: Du kan söka i form av
module!function.
Hovra över varje händelse för att få mer information via verktygstips. Om du väljer en händelse körs frågan för händelsen och mer information visas. När du dubbelklickar på en händelse, flyttas du till den platsen i TTD-spårningsfilen.
Exceptions
När du läser in en spårningsfil och tidslinjen är aktiv visas eventuella undantag i inspelningen automatiskt.
När du hovrar över en brytpunkt visas information som undantagstypen och undantagskoden.
Du kan filtrera ytterligare på en specifik undantagskod med hjälp av det valfria fältet Undantagskod .
Du kan också lägga till en ny tidslinje för en specifik undantagstyp.
Brytpunkter
När du har lagt till en brytpunkt visar positionerna på tidslinjen dig när brytpunkten nås. Du kan till exempel använda kommandot bp Set Breakpoint. När du hovra över en brytpunkt visas adressen och instruktionspekaren som är associerad med brytpunkten.
När brytpunkten rensas tas tidslinjen för den associerade brytpunkten bort automatiskt.
Funktionsanrop
Du kan se positionerna för funktionsanrop på tidslinjen. Om du vill göra det här steget anger du sökningen i form av module!function. Ett exempel är TimelineTestCode!multiplyTwo. Du kan också ange jokertecken, till exempel TimelineTestCode!m*.
När du hovra över ett funktionsanrop visas funktionsnamnet, indataparametrarna, deras värden och returvärdet. Det här exemplet visar bufferten och storleken eftersom de är parametrarna för DisplayGreeting!GetCppConGreeting.
Minnesåtkomst
Använd tidslinjen minnesåtkomster för att se när ett visst minnesintervall lästes eller skrevs till, eller var kodkörningen ägde rum. Start- och stoppadresser används för att definiera ett intervall mellan två minnesadresser.
När du hovra över ett minnesåtkomstobjekt visas värdet och instruktionspekaren.
Arbeta med tidslinjer
En lodrät grå linje följer markören när du hovra över tidslinjen. Den lodräta blå linjen anger den aktuella positionen i spårningen.
Välj ikonerna för förstoringsglas för att zooma in och ut på tidslinjen.
Använd rektangeln för att panorera tidslinjens vy i det övre kontrollområdet för tidslinjen. Dra rektangelns yttre avgränsare för att ändra storlek på den aktuella tidslinjevyn.
Musrörelser
Om du vill zooma in och ut väljer du Ctrl och använder rullningshjulet.
Om du vill panorera från sida till sida väljer du Skift och använder rullningshjulet.
Felsökningstekniker för tidslinje
För att demonstrera tekniker för felsökning av tidslinjen återanvänds genomgången av felsökning av tidsresor här. Den här demonstrationen förutsätter att du har slutfört de två första stegen för att skapa exempelkoden och skapat TTD-inspelningen med hjälp av de två första stegen som beskrivs där.
I det här scenariot är det första steget att hitta undantaget i tidsresespårningen. Dubbelklicka på det enda undantag som visas på tidslinjen.
I kommandofönstret kan du se att följande kommando utfärdades när du valde undantaget.
(2dcc.6600): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: CC:0
@$curprocess.TTD.Events.Where(t => t.Type == "Exception")[0x0].Position.SeekTo()
Välj Visa>register för att visa registren nu på tidslinjen för att påbörja undersökningen.
I kommandoutdata pekar stacken (esp) och baspekaren (ebp) på olika adresser. Den här avvikelsen kan tyda på stackkorruption. Möjligen returnerade en funktion och skadade sedan stacken. Om du vill verifiera det här problemet går du tillbaka till innan processortillståndet skadades och ser om du kan avgöra när stacken skadades.
När du gör det undersöker du värdena för lokala variabler och stacken:
- Välj Visa>lokala värden för att visa de lokala värdena.
- Välj Visa>Stack för att visa kodkörningsstacken.
När ett fel uppstår är det vanligt att i spårningen hamna ett par steg efter orsaken i felhanteringskoden. Med tidsresor kan du gå tillbaka en instruktion i taget för att lokalisera den verkliga grundorsaken.
I menyfliksområdet Start använder du kommandot Step Into Back för att stega tillbaka tre instruktioner. När du gör den här processen fortsätter du att undersöka fönstren Stack, Locals och Registers .
Fönstret Kommando visar tidsresepositionen och registren när du stegar tillbaka tre instruktioner.
0:000> t-
Time Travel Position: CB:41
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00540020 esp=003cf7d0 ebp=00520055 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
00540020 ?? ???
0:000> t-
Time Travel Position: CB:40
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00061767 esp=003cf7cc ebp=00520055 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
DisplayGreeting!main+0x57:
00061767 c3 ret
0:000> t-
Time Travel Position: CB:3A
eax=0000004c ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=0006175f esp=003cf718 ebp=003cf7c8 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
DisplayGreeting!main+0x4f:
0006175f 33c0 xor eax,eax
Vid denna punkt under spårningen har stacken och baspekaren värden som är mer logiska. Det verkar som om du närmar dig den punkt i koden där skadan inträffade.
esp=003cf718 ebp=003cf7c8
Fönstret Lokalt innehåller värden från målappen. Källkodsfönstret visar den kodrad som är redo att köras i källkoden vid den här tidpunkten i spårningen.
Om du vill undersöka saken ytterligare öppnar du ett minnesfönster för att visa innehållet nära stackpekarens minnesadress (esp). I det här exemplet har det värdet 003cf7c8. Välj Minnestext>>ASCII för att visa DEN ASCII-text som lagras på adressen.
Tidslinje för minnesåtkomst
När en minnesplats har identifierats använder du det värdet för att lägga till en tidslinje för minnesåtkomst. Välj + Lägg till tidslinje och fyll i startadressen. Titta på 4 byte så att när du lägger till dem i startadress till 003cf7c8, har du en slutadress003cf7cb. Standardvärdet är att titta på alla minnesskrivningar, men du kan också bara titta på skrivningar eller kodkörning på den adressen.
Nu kan du bläddra igenom tidslinjen i omvänd ordning för att undersöka vid vilken tidpunkt i denna tidsreseföljd som den här minnesplatsen skrevs för att upptäcka vad du kan hitta. När du väljer den här positionen på tidslinjen kan du se att lokalbefolkningen värderar olika värden för strängen som kopieras. Målvärdet verkar vara ofullständigt, vilket tyder på att längden på strängen inte är korrekt.
Tidslinje för brytpunkt
Att använda brytpunkter är en vanlig metod för att pausa kodexekvering vid någon händelse av intresse. Med TTD kan du ange en brytpunkt och resa tillbaka i tiden tills brytpunkten nås när spårningen har registrerats. Möjligheten att undersöka processtillståndet när ett problem inträffar, för att fastställa den bästa platsen för en brytpunkt, möjliggör fler felsökningsarbetsflöden som är unika för TTD.
Om du vill utforska en alternativ felsökningsteknik för tidslinjen väljer du undantaget i tidslinjen och går återigen tre steg tillbaka med hjälp av kommandot Step Into Back i menyfliksområdet Start .
I det här lilla exemplet är det enkelt att titta i koden. Om du har hundratals rader med kod och dussintals subrutiner kan du använda de tekniker som beskrivs här för att minska tiden som krävs för att hitta problemet.
Som tidigare nämnts pekar baspekaren (esp) på meddelandetexten i stället för att peka på en instruktion.
ba Använd kommandot för att ange en brytpunkt för minnesåtkomst. Du anger en w - skriv brytpunkt för att se när det här minnesområdet skrivs till.
0:000> ba w4 003cf7c8
Även om du använder en enkel brytpunkt för minnesåtkomst kan du skapa brytpunkter så att de blir mer komplexa villkorssatser. Mer information finns i bp, bu, bm (Set Breakpoint).
På startmenyn väljer du Gå tillbaka för att resa tillbaka i tiden tills brytpunkten har nåtts.
Nu kan du undersöka programstacken för att se vilken kod som är aktiv.
Eftersom det är osannolikt att den Microsoft-tillhandahållna wscpy_s() funktionen kan ha ett kodfel som detta kan du titta längre i stacken. Stacken visar att Greeting!main anropar Greeting!GetCppConGreeting. I det lilla kodexemplet kan du öppna koden just nu och förmodligen enkelt hitta felet. Men för att illustrera de tekniker som du kan använda med ett större, mer komplext program lägger du till en tidslinje för funktionsanrop.
Tidslinje för funktionsanrop
Välj + Lägg till tidslinje och fyll i DisplayGreeting!GetCppConGreeting för funktionens söksträng.
Kryssrutorna Startplats och Slutplats anger start och slut för ett funktionsanrop i spårningen.
Du kan använda dx kommandot för att visa funktionsanropsobjektet för att se de associerade TimeStart fälten och TimeEnd fälten som motsvarar startplatsen och slutplatsen för funktionsanropet.
dx @$cursession.TTD.Calls("DisplayGreeting!GetCppConGreeting")[0x0]
EventType : 0x0
ThreadId : 0x6600
UniqueThreadId : 0x2
TimeStart : 6D:BD [Time Travel]
SystemTimeStart : Thursday, October 31, 2019 23:36:05
TimeEnd : 6D:742 [Time Travel]
SystemTimeEnd : Thursday, October 31, 2019 23:36:05
Function : DisplayGreeting!GetCppConGreeting
FunctionAddress : 0x615a0
ReturnAddress : 0x61746
Parameters
Antingen en av kryssrutorna Startplats eller Slutplats eller båda kryssrutorna Startplats och Slutplats måste markeras.
Din kod är inte rekursiv eller återkommande, så det är enkelt att hitta den på tidslinjen GetCppConGreeting när metoden anropas. Anropet till GetCppConGreeting inträffar också samtidigt som brytpunkten och minnesåtkomsthändelsen som du definierade. Det verkar därför som om du har begränsat till ett kodområde för att titta noga på grundorsaken till programkraschen.
Utforska kodkörning genom att visa flera tidslinjer
Även om vårt kodexempel är litet möjliggör tekniken att använda flera tidslinjer visuell utforskning av en tidsresespårning. Du kan titta i spårningsfilen för att ställa frågor, till exempel "När används ett minnesområde innan en brytpunkt nås?".
Möjligheten att se fler korrelationer och hitta oväntade saker skiljer tidslinjeverktyget från att interagera med tidsresespårningen med hjälp av kommandoradskommandon.
Tidslinjebokmärken
Bokmärk viktiga tidsresepositioner i WinDbg istället för att kopiera och klistra in dem manuellt till Notepad. Bokmärken gör det enklare att snabbt visa olika positioner i spårningen i förhållande till andra händelser och kommentera dem.
Du kan ange ett beskrivande namn för bokmärken.
Välj Visa>tidslinje för att öppna fönstret Tidslinjer så att du kan komma åt bokmärken-tidslinjen. När du hovrar över ett bokmärke visas bokmärkets namn.
Högerklicka på bokmärket för att gå till bokmärkespositionen, byta namn på bokmärket eller ta bort det.
Anmärkning
Bokmärkesfunktionen är inte tillgänglig i version 1.2402.24001.0 av WinDbg.