Övning – Felsöka med Visual Studio Code

Slutförd

Det är dags att omsätta dina nyligen förvärvade felsökningskunskaper i praktiken. Det är din första dag på jobbet och du får genast användning för dina kunskaper om .NET-felsökning när du ska korrigera en bugg i företagets flaggskeppsprodukt, en Fibonacci-kalkylator.

Skapa ett .NET-exempelprojekt för felsökning

Innan vi kan konfigurera Visual Studio Code för .NET-felsökning behöver vi ett .NET-projekt. Visual Studio Code har en integrerad terminal som gör det enkelt att skapa ett nytt projekt.

  1. I Visual Studio Code väljer du Arkiv>Öppna mapp.

  2. Skapa en ny mapp med namnet DotNetDebugging på önskad plats. Välj sedan Välj mapp.

  3. Öppna den integrerade terminalen från Visual Studio Code genom att välja Visa>terminal på huvudmenyn.

  4. Kopiera och klistra in följande kommando i terminalfönstret:

    dotnet new console
    

    Det här kommandot skapar en Program.cs fil i mappen med ett grundläggande "Hello World"-program redan skrivet. Den skapar också en C#-projektfil med namnet DotNetDebugging.csproj.

  5. Kopiera och klistra in följande kommando i terminalfönstret för att köra ”Hello World”-programmet.

    dotnet run
    

    Terminalfönstret visar "Hello World!" som utdata.

Konfigurera Visual Studio Code för .NET-felsökning

  1. Öppna Program.cs genom att välja den.

  2. Första gången du öppnar en C#-fil i Visual Studio Code uppmanas du att installera rekommenderade tillägg för C#. Om du ser den här uppmaningen väljer du knappen Installera i kommandotolken.

    Skärmbild av Visual Studio Code-uppmaningen om att installera C#-tillägget.

  3. Visual Studio Code installerar C#-tillägg och visar en annan uppmaning om att lägga till nödvändiga tillgångar för att skapa och felsöka ditt projekt. Välj knappen Ja .

    Skärmbild av Visual Studio Code-prompten om att lägga till nödvändiga tillgångar för att skapa och felsöka ditt .NET-projekt.

  4. Du kan stänga fliken Tillägg: C# för att fokusera på koden som vi ska felsöka.

Lägga till Fibonacci-programlogiken

Vårt projekt skriver ett ”Hello World”-meddelande till konsolen, vilket inte ger oss mycket att felsöka. I stället använder du ett kort .NET-program för att beräkna N:e numret i Fibonacci-sekvensen.

Fibonaccisekvensen är en serie med tal som börjar med talet 0 och 1, och där varje efterföljande tal är summan av de två föregående talen. Sekvensen fortsätter på följande sätt:

0, 1, 1, 2, 3, 5, 8, 13, 21...
  1. Öppna Program.cs genom att välja den.

  2. Ersätt innehållet i Program.cs med följande kod:

    int result = Fibonacci(5);
    Console.WriteLine(result);
    
    static int Fibonacci(int n)
    {
        int n1 = 0;
        int n2 = 1;
        int sum;
    
        for (int i = 2; i < n; i++)
        {
            sum = n1 + n2;
            n1 = n2;
            n2 = sum;
        }
    
        return n == 0 ? n1 : n2;
    }
    

    Kommentar

    Den här koden innehåller ett fel, som vi ska felsöka senare i den här modulen. Använd inte koden i verksamhetskritiska Fibonacci-program förrän vi har korrigerat buggen.

  3. Spara filen genom att välja Ctrl+S för Windows och Linux. Välj Cmd+S för Mac.

  4. Nu ska vi ta en titt på hur den uppdaterade koden fungerar innan vi felsöker den. Kör programmet genom att ange följande kod i terminalen:

    dotnet run
    

    Terminalfönster med ändrade programutdata.

  5. Resultatet 3, visas i terminalutdata. När du läser det här Fibonacci-sekvensdiagrammet som visar den nollbaserade sekvenspositionen för varje värde inom parentes ser du att resultatet borde ha varit 5. Det är dags att vi bekantar oss med felsökningsprogrammet och åtgärdar programmet.

    0 (0), 1 (1), 1 (2), 2 (3), 3 (4), 5 (5), 8 (6), 13 (7), 21 (8)...
    

Analysera problemen

  1. Starta programmet genom att välja fliken Kör och felsöka till vänster och välj sedan knappen Starta felsökning . Du kan behöva välja knappen Kör och felsöka först och sedan välja filen Program.cs .

    Skärmbild av knappen Starta felsökning i Visual Studio Code.

    Du bör se att programmet slutförs snabbt. Det är normalt eftersom du inte har lagt till några brytpunkter ännu.

  2. Om felsökningskonsolen inte visas väljer du Ctrl+Skift+Y för Windows och Linux eller Cmd+Skift+Y för Mac. Nu ska flera rader med diagnostikinformation visas, följt av:

    ...
    Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.0\System.Threading.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.0\System.Text.Encoding.Extensions.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    3
    The program '[88820] DotNetDebugging.dll' has exited with code 0 (0x0).
    

De översta raderna anger att de förvalda felsökningsinställningarna aktiverar alternativet ”Just My Code”. Det innebär att felsökaren bara felsöker koden och inte går in i källkoden för .NET om du inte inaktiverar det här läget. Det här alternativet gör att du kan fokusera helt på att felsöka din kod.

Sist i felsökningskonsolens utdata ser du att programmet skriver ”3” till konsolen, och sedan avslutar med koden 0. Normalt indikerar slutkoden 0 att programmet kördes och avslutades utan krasch. Det är dock skillnad på att krascha och att returnera rätt värde. I det här fallet bad vi programmet att beräkna det femte värdet i Fibonacci-sekvensen:

0 (0), 1 (1), 1 (2), 2 (3), 3 (4), 5 (5), 8 (6), 13 (7), 21 (8)...

Det femte värdet i listan är 5, men vårt program returnerade 3. Vi ska använda felsökningsprogrammet för att diagnostisera och åtgärda det här felet.

Använda brytpunkter och steg för steg-körning

  1. Lägg till en brytpunkt genom att klicka på vänstermarginalen på rad 1int result = Fibonacci(5);.

    Skärmbild av brytpunktsplatsen i koden.

  2. Starta felsökningen igen. Programmet börjar köras. Den bryter (pausar körningen) på rad 1 på grund av den brytpunkt som du anger. Använd felsökningskontrollerna och stega in i funktionen Fibonacci().

    Skärmbild av knappen Stega in.

Kontrollera tillståndet för variabler

Nu tar det lite tid att inspektera de olika variablernas värden med hjälp av panelen Variabler .

Skärmbild av panelen Variabler.

  • Vilket värde visas för parametern n?
  • Vad är värdena för de lokala variablerna n1, n2 och sum när funktionen började köra?
  1. Nu ska vi använda felsökningskontrollen for (Gå förbi) för att gå till -loopen.

    Skärmbild av knappen Steg över.

  2. Fortsätt tills du kommer till den första raden i for-loopen, på raden som ser ut så här:

    sum = n1 + n2;
    

Kommentar

Du har kanske lagt märke till att det krävs flera steg i kommandon för att gå igenom raden for(...) {}. Den här situationen beror på att det finns flera satser på den här raden. När du stegar går du vidare till nästa instruktion i koden. Det finns vanligtvis en instruktion per rad. Om så inte är fallet behöver du flera steg för att gå vidare till nästa rad.

Studera koden

En viktig del av felsökningen är att stanna upp och försöka förstå vad de olika delarna av koden (både funktioner och block, t.ex. loopar) gör. Det gör ingenting om du inte är säker, det hör till när du felsöker. Men genom att engagera dig i felsökningsprocessen blir det enklare att snabbt hitta buggarna.

Så, Fibonacci-sekvensen är alltså en serie tal som börjar med 0 och 1, där vartannat efterföljande tal utgör summan av de två föregående talen.

Det betyder att:

Fibonacci(0) = 0
Fibonacci(1) = 1
Fibonacci(2) = 1 (0 + 1)
Fibonacci(3) = 2 (1 + 1)
Fibonacci(4) = 3 (1 + 2)
Fibonacci(5) = 5 (2 + 3)

Vi kan dra följande slutsatser från for-loopen:

  1. Loopen räknar från 2 till n (det tal i Fibonacci-sekvensen som vi letar efter).
  2. Om n är mindre än 2 kommer loopen inte att köras. return-instruktionen sist i funktionen returnerar 0 om n är 0, och 1 om n är 1 eller 2. Det här är per definition de nollte, första och andra värdena i Fibonacci-serien.
  3. Ännu intressantare blir det när n är större än 2. I detta fall definieras det aktuella värdet som summan av de föregående två värdena. Så, i den här loopen är n1 och n2 de föregående två värdena och sum är värdet för den aktuella iterationen. Det betyder att varje gång som vi får fram summan av de föregående två värdena och anger den till sum, så uppdateras våra n1- och n2-värden.

Ok, vi kan stanna här. Vi kan låta felsökningsprogrammet ta över. Men det kan vara bra att gå igenom koden för att se om den gör det den ska, och förstå när den inte gör det.

Hitta felet med brytpunkter

Att gå igenom koden kan vara användbart men omständligt, särskilt när du arbetar med loopar eller annan kod som anropas upprepade gånger. I stället för att stega igenom koden om och om igen kan vi ställa in en ny brytpunkt på den första raden i loopen.

Det är viktigt att lägga till brytpunkter på rätt plats. Vi är särskilt intresserade av sumvärdet för , eftersom det representerar det aktuella maximala Fibonacci-värdet. Därför ska vi placera brytpunkten på raden eftersum att har angetts.

  1. Lägg till en andra brytpunkt på rad 13.

    Skärmbild som visar att en andra brytpunkt ställs in.

    Kommentar

    Om du kör koden och märker att du ofta stegar en rad eller två, kan du enkelt uppdatera brytpunkterna till de rader som är mest effektiva.

  2. Nu när vi har en lämplig brytpunkt i loopen, använd felsökningskontrollen Fortsätt för att gå vidare tills brytpunkten har nåtts. När vi tittar på våra lokala variabler ser vi följande rader:

    n [int]: 5
    n1 [int]: 0
    n2 [int]: 1
    sum [int]: 1
    i [int]: 2
    

    Dessa rader verkar vara korrekta. Första gången i loopen är sum av de föregående två värdena 1. I stället för att stega igenom koden rad för rad kan vi använda brytpunkterna och snabbt hoppa till dem i loopen.

  3. Välj Fortsätt för att fortsätta programflödet tills nästa brytpunkt har nåtts, som kommer att vara på nästa pass genom loopen.

    Kommentar

    Var inte alltför orolig för att hoppa över buggen när du använder Fortsätt. Du kommer troligtvis att behöva felsöka koden flera gånger innan du hittar problemet. Det går ofta snabbare att köra genom koden några gånger i stället för att vara alltför noggrann när du stegar igenom.

    Den här gången får vi följande värden:

    n [int]: 5
    n1 [int]: 1
    n2 [int]: 1
    sum [int]: 2
    i [int]: 3
    

    Studera värdena. Stämmer värdena fortfarande? Det verkar så. För det tredje Fibonacci-talet förväntar vi oss att sum ska vara 2, och det stämmer.

  4. Okej, vi väljer Fortsätt för att loopa den igen.

    n [int]: 5
    n1 [int]: 1
    n2 [int]: 2
    sum [int]: 3
    i [int]: 4
    

    Allt ser fortfarande bra ut. Vi förväntar oss att det fjärde värdet i serien ska vara 3.

  5. Kanske börjar du undra om inte koden var rätt redan från början, och om buggen var ren inbillning. Vi kör igenom loopen en sista gång. Välj Fortsätt en gång till.

    Vänta lite. Programmet returnerar 3! Det stämmer inte.

    Okej, ingen fara. Vi har inte misslyckats, vi har lärt oss något. Nu vet vi att koden loopar som den ska tills i är lika med 4, men att den avslutas innan det sista värdet beräknats. Jag börjar få några idéer om var buggen är. Är du det?

  6. Nu ska vi ange ytterligare en brytpunkt på rad 17, som lyder:

    return n == 0 ? n1 : n2;
    

    Den här brytpunkten gör att vi kan inspektera programtillståndet innan funktionen avslutas. Vi har redan lärt oss allt vi kan förvänta oss från våra tidigare brytpunkter på rad 1 och 13, så att vi kan rensa dem.

  7. Ta bort de tidigare brytpunkterna på raderna 1 och 13. Du kan göra det genom att klicka på dem i marginalen bredvid radnumren, eller genom att avmarkera kryssrutorna för brytpunkten för raderna 1 och 13 i fönstret Brytpunkter längst ned till vänster.

    Skärmbild som visar brytpunkterna i fönstret Brytpunkter.

    Nu när vi vet mycket mer om vad som händer och har lagt till en brytpunkt som hejdar programmet när det inte beter sig som förväntat, bör vi kunna fånga in buggen.

  8. Nu ska vi starta felsökningsprogrammet en sista gång.

    n [int]: 5
    n1 [int]: 2
    n2 [int]: 3
    sum [int]: 3
    

    Hm, det stämmer inte. Vi bad specifikt om Fibonaccci(5), och vi fick Fibonacci(4). Den här funktionen returnerar n2, och varje loopiteration beräknar sum-värdet och ställer in n2 till sum.

    Baserat på den här informationen och vår tidigare felsökning kan vi se att loopen avslutades när i var 4, inte 5.

    Nu ska vi titta närmare på den första raden i for-loopen.

    for (int i = 2; i < n; i++)
    

    Okej, vänta lite! Det innebär att den avslutas så snart som toppen av for-loopen ser att i inte längre är mindre än n. Det innebär att loopkoden inte körs när i är lika med n. Det verkar som om det vi ville var att köra fram till i <= n, men i stället:

    for (int i = 2; i <= n; i++)
    

    Med den ändringen bör det uppdaterade programmet se ut så här:

    int result = Fibonacci(5);
    Console.WriteLine(result);
    
    static int Fibonacci(int n)
    {
        int n1 = 0;
        int n2 = 1;
        int sum;
    
        for (int i = 2; i <= n; i++)
        {
            sum = n1 + n2;
            n1 = n2;
            n2 = sum;
        }
    
        return n == 0 ? n1 : n2;
    }
    
  9. Stoppa felsökningen om du inte redan gjort det.

  10. Gör sedan den föregående ändringen till rad 10 och lämna vår brytpunkt på rad 17.

  11. Starta om felsökningsprogrammet. Den här gången visas följande värden när vi når brytpunkten på rad 17:

    n [int]: 5
    n1 [int]: 3
    n2 [int]: 5
    sum [int]: 5
    

    Ja! Vi fick till det! Utmärkt jobbat, du har räddat situationen för Fibonacci, Inc.!

  12. Välj Fortsätt bara för att se till att programmet returnerar rätt värde.

    5
    The program '[105260] DotNetDebugging.dll' has exited with code 0 (0x0).
    

    Och nu returneras rätt utdata.

Nu är du klar! Du har felsökt färdigskriven kod med hjälp av .NET-felsökningsprogrammet i Visual Studio Code.

I nästa lektion tittar vi på hur du kan använda loggnings- och spårningsfunktionerna som är inbyggda i .NET för att enkelt felsöka din egen kod.