Kommentar
Å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.
För Windows 8 har felsökningsprogrammet och Windows-kompilatorn förbättrats så att du kan felsöka optimerad kod och felsöka infogade funktioner. Felsökningsprogrammet visar parametrar och lokala variabler oavsett om de lagras i register eller i stacken. Felsökningsprogrammet visar även infogade funktioner i anropsstacken. För infogade funktioner visar felsökningsprogrammet lokala variabler, men inte parametrar.
När koden optimeras omvandlas den så att den körs snabbare och använder mindre minne. Ibland tas funktioner bort som ett resultat av borttagning av död kod, sammanslagning av kod, eller när funktioner placeras inline. Lokala variabler och parametrar kan också tas bort. Många kodoptimeringar tar bort lokala variabler som inte behövs eller används. andra optimeringar tar bort induktionsvariabler i loopar. Gemensam eliminering av underuttryck sammanfogar lokala variabler.
Detaljhandelsversioner av Windows är optimerade. Så om du kör en detaljhandelsversion av Windows är det särskilt användbart att ha ett felsökningsprogram som är utformat för att fungera bra med optimerad kod. För att felsöka optimerad kod krävs två primära funktioner: 1) korrekt visning av lokala variabler och 2) visning av infogade funktioner i anropsstacken.
Korrekt visning av lokala variabler och parametrar
För att underlätta korrekt visning av lokala variabler och parametrar registrerar kompilatorn information om platserna för lokala variabler och parametrar i symbolfiler (PDB). Dessa platsinformationer spårar variablernas lagringsplatser och de specifika kodintervall där dessa lagringar är giltiga. Dessa poster hjälper inte bara till att spåra variablernas platser (i register eller i stackfack) utan även variablernas förflyttning. En parameter kan till exempel först vara i registret RCX, men flyttas till ett stackfack för att frigöra RCX, sedan flyttas den för att registrera R8 när den används mycket i en loop och sedan flyttas till ett annat stackfack när koden är utanför loopen. Windows-felsökningsprogrammet använder de omfattande platsposterna i PDB-filerna och använder den aktuella instruktionspekaren för att välja lämpliga platsposter för de lokala variablerna och parametrarna.
Den här skärmbilden av fönstret Locals i Visual Studio visar parametrarna och de lokala variablerna för en funktion i ett optimerat 64-bitarsprogram. Funktionen är inte i inline, så vi ser både parametrar och lokala variabler.
Du kan använda dv -v-kommandot för att se platserna för parametrarna och de lokala variablerna.
Observera att fönstret Locals visar parametrarna korrekt trots att de lagras i register.
Förutom att spåra variabler med primitiva typer, spårar platsregistren också datamedlemmar i lokala strukturer och klasser. Följande felsökningsutdata visar lokala strukturer.
0:000> dt My1
Local var Type _LocalStruct
+0x000 i1 : 0n0 (edi)
+0x004 i2 : 0n1 (rsp+0x94)
+0x008 i3 : 0n2 (rsp+0x90)
+0x00c i4 : 0n3 (rsp+0x208)
+0x010 i5 : 0n4 (r10d)
+0x014 i6 : 0n7 (rsp+0x200)
0:000> dt My2
Local var @ 0xefa60 Type _IntSum
+0x000 sum1 : 0n4760 (edx)
+0x004 sum2 : 0n30772 (ecx)
+0x008 sum3 : 0n2 (r12d)
+0x00c sum4 : 0n0
Här följer några observationer kring föregående felsökningsutdata.
- Den lokala strukturen My1 visar att kompilatorn kan sprida medlemmar i lokala strukturdata till register och icke-sammanhängande stackfack.
- Utdata från kommandot dt My2 skiljer sig från utdata från kommandot dt _IntSum 0xefa60. Du kan inte anta att den lokala strukturen upptar ett sammanhängande block med stackminne. När det gäller My2 stannar bara
sum4kvar i det ursprungliga stackblocket. De övriga tre datamedlemmarna flyttas till register. - Vissa datamedlemmar kan ha flera platser. My2.sum2 har till exempel två platser: en är registrera ECX (som Windows-felsökaren väljer) och den andra är 0xefa60+0x4 (det ursprungliga stackfacket). Detta kan inträffa även för lokala variabler av primitiv typ, och Windows-felsökaren tillämpar prejudikat-heuristik för att avgöra vilken plats som ska användas. Till exempel trumfar alltid registerplatser stackplatser.
Visning av infogade funktioner i anropsstacken
Under kodoptimeringen placeras vissa funktioner i rad. Det vill säga, funktionens kropp placeras direkt i koden som en makroexpansion. Det finns inget funktionsanrop och ingen återgång till anroparen. För att underlätta visningen av infogade funktioner lagrar kompilatorn data i PDB-filerna som hjälper till att avkoda kodsegmenten för infogade funktioner (det vill säga sekvenser av kodblock i anroparfunktioner som tillhör de anropande funktioner som placeras infogade) samt de lokala variablerna (begränsade lokala variabler i dessa kodblock). Dessa data hjälper felsökningsprogrammet att inkludera inlinefunktioner som en del av stackens upplösning.
Anta att du kompilerar ett program och tvingar en funktion med namnet func1 att vara infogad.
__forceinline int func1(int p1, int p2, int p3)
{
int num1 = 0;
int num2 = 0;
int num3 = 0;
...
}
Du kan använda bm-kommandot för att ange en brytpunkt på func1.
0:000> bm MyApp!func1
1: 000007f6`8d621088 @!"MyApp!func1" (MyApp!func1 inlined in MyApp!main+0x88)
0:000> g
Breakpoint 1 hit
MyApp!main+0x88:
000007f6`8d621088 488d0d21110000 lea rcx,[MyApp!`string' (000007f6`8d6221b0)]
När du har lagt till ett steg i func1kan du använda kommandot k för att se func1 i anropsstacken. Du kan använda dv-kommandot för att se de lokala variablerna för func1. Observera att den lokala variabeln num3 visas som otillgänglig. En lokal variabel kan vara otillgänglig i optimerad kod av flera orsaker. Det kan vara så att variabeln inte finns i den optimerade koden. Det kan vara så att variabeln inte har initierats ännu eller att variabeln inte längre används.
0:000> p
MyApp!func1+0x7:
000007f6`8d62108f 8d3c33 lea edi,[rbx+rsi]
0:000> knL
# Child-SP RetAddr Call Site
00 (Inline Function) --------`-------- MyApp!func1+0x7
01 00000000`0050fc90 000007f6`8d6213f3 MyApp!main+0x8f
02 00000000`0050fcf0 000007ff`c6af0f7d MyApp!__tmainCRTStartup+0x10f
03 00000000`0050fd20 000007ff`c7063d6d KERNEL32!BaseThreadInitThunk+0xd
04 00000000`0050fd50 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
0:000> dv -v
00000000`0050fcb0 num1 = 0n0
00000000`0050fcb4 num2 = 0n0
<unavailable> num3 = <value unavailable>
Om du tittar på bildruta 1 i stackspårningen kan du se de lokala variablerna för main funktionen. Observera att två av variablerna lagras i register.
0:000> .frame 1
01 00000000`0050fc90 000007f6`8d6213f3 MyApp!main+0x8f
0:000> dv -v
00000000`0050fd08 c = 0n7
@ebx b = 0n13
@esi a = 0n6
Windows-felsökningsprogrammet aggregerar data från PDB-filer för att hitta alla platser där en specifik funktion har placerats infogad. Du kan använda x-kommandot för att lista alla anroparwebbplatser för en infogad funktion.
0:000> x simple!MoreCalculate
00000000`ff6e1455 simple!MoreCalculate = (inline caller) simple!wmain+8d
00000000`ff6e1528 simple!MoreCalculate = (inline caller) simple!wmain+160
0:000> x simple!Calculate
00000000`ff6e141b simple!Calculate = (inline caller) simple!wmain+53
Eftersom Windows-felsökaren kan räkna upp alla anroparwebbplatser för en infogad funktion kan den ange brytpunkter i den infogade funktionen genom att beräkna förskjutningarna från anroparwebbplatserna. Du kan använda bm-kommandot (som används för att ange brytpunkter som matchar mönster för reguljära uttryck) för att ange brytpunkter för infogade funktioner.
Windows-felsökningsprogrammet grupperar alla brytpunkter som har angetts för en specifik infogad funktion i en brytpunktscontainer. Du kan ändra brytpunktsbehållaren som helhet med hjälp av kommandon som be, bd, bc. Se följande kommandoexempel för bd 3 och bc 3 . Du kan också ändra enskilda brytpunkter. Se följande kommandoexempel be 2 .
0:000> bm simple!MoreCalculate
2: 00000000`ff6e1455 @!"simple!MoreCalculate" (simple!MoreCalculate inlined in simple!wmain+0x8d)
4: 00000000`ff6e1528 @!"simple!MoreCalculate" (simple!MoreCalculate inlined in simple!wmain+0x160)
0:000> bl
0 e 00000000`ff6e13c8 [n:\win7\simple\simple.cpp @ 52] 0001 (0001) 0:**** simple!wmain
3 e <inline function> 0001 (0001) 0:**** {simple!MoreCalculate}
2 e 00000000`ff6e1455 [n:\win7\simple\simple.cpp @ 58] 0001 (0001) 0:**** simple!wmain+0x8d (inline function simple!MoreCalculate)
4 e 00000000`ff6e1528 [n:\win7\simple\simple.cpp @ 72] 0001 (0001) 0:**** simple!wmain+0x160 (inline function simple!MoreCalculate)
0:000> bd 3
0:000> be 2
0:000> bl
0 e 00000000`ff6e13c8 [n:\win7\simple\simple.cpp @ 52] 0001 (0001) 0:**** simple!wmain
3 d <inline function> 0001 (0001) 0:**** {simple!MoreCalculate}
2 e 00000000`ff6e1455 [n:\win7\simple\simple.cpp @ 58] 0001 (0001) 0:**** simple!wmain+0x8d (inline function simple!MoreCalculate)
4 d 00000000`ff6e1528 [n:\win7\simple\simple.cpp @ 72] 0001 (0001) 0:**** simple!wmain+0x160 (inline function simple!MoreCalculate)
0:000> bc 3
0:000> bl
0 e 00000000`ff6e13c8 [n:\win7\simple\simple.cpp @ 52] 0001 (0001) 0:**** simple!wmain
Eftersom det inte finns några explicita anrops- eller returinstruktioner för infogade funktioner är steg på källnivå särskilt utmanande för ett felsökningsprogram. Du kan till exempel oavsiktligt gå in i en infogad funktion (om nästa instruktion är en del av en infogad funktion), eller så kan du gå in och gå ut ur samma infogade funktion flera gånger (eftersom kodblocken för den infogade funktionen har delats och flyttats av kompilatorn). För att bevara den välbekanta stegupplevelsen har Windows-felsökaren en liten konceptuell anropsstack för varje kodinstruktionsadress och skapar en intern tillståndsmaskin för att utföra steg-in, steg-över och steg-ut operationer. Detta ger en någorlunda exakt uppskattning av stegupplevelsen för icke-infogade funktioner.
ytterligare information
Observera Du kan använda kommandot .inline 0 för att inaktivera felsökning av infogade funktioner. Kommandot .inline 1 aktiverar felsökning av infogade funktioner. standardtekniker för felsökning