Oefening: Fouten opsporen met Visual Studio Code

Voltooid

Het is tijd om uw zojuist verworven kennis over foutopsporing in de praktijk te brengen. Het is uw eerste dag op het werk en tijd om uw .NET-foutopsporingsvaardigheden te demonstreren door een bug te corrigeren in het belangrijkste product van het bedrijf, een Fibonacci-rekenmachine.

Een voorbeeld van een .NET-project maken voor foutopsporing

Als u Visual Studio Code voor foutopsporing met .NET wilt instellen, hebt u eerst een .NET-project nodig. Visual Studio Code omvat een geïntegreerde terminal, waarmee eenvoudig een nieuw project kan worden gemaakt.

  1. Selecteer in Visual Studio Code Bestand>Map openen.

  2. Maak een nieuwe map met de naam DotNetDebugging op de locatie van uw keuze. Kies Vervolgens Map selecteren.

  3. Open de geïntegreerde terminal vanuit Visual Studio Code door in het hoofdmenu Weergeven>Terminal te selecteren.

  4. Kopieer en plak de volgende opdracht in het terminalvenster:

    dotnet new console
    

    Met deze opdracht maakt u in de map het bestand Program.cs, waarin al een eenvoudig Hallo wereld-programma is geschreven. Er wordt ook een C#-projectbestand gemaakt met de naam DotNetDebugging.csproj.

  5. Kopieer de volgende opdracht en plak deze in het terminalvenster om het Hallo wereld-programma uit te voeren.

    dotnet run
    

    In het terminalvenster wordt 'Hallo wereld!' weergegeven als uitvoer.

Visual Studio Code instellen voor foutopsporing met .NET

  1. Open Program.cs door het te selecteren.

  2. De eerste keer dat u een C#-bestand opent in Visual Studio Code, wordt u gevraagd om aanbevolen extensies voor C# te installeren. Als u deze prompt ziet, selecteert u de knop Installeren in de prompt.

    Schermopname van de prompt in Visual Studio Code voor het installeren van de extensie voor C#.

  3. Visual Studio Code installeert de C# -extensie en toont een andere prompt om vereiste assets toe te voegen om uw project te bouwen en fouten op te sporen. Selecteer de knop Ja.

    Schermopname van de prompt in Visual Studio Code voor het toevoegen van de vereiste assets om fouten in uw .NET-project op te sporen.

  4. U kunt het tabblad Extensie: C# sluiten om te focussen op de code die we gaan opsporen.

De Fibonacci-programmalogica toevoegen

Door het huidige project wordt het bericht 'Hallo wereld' naar de console geschreven. Hiermee kunnen niet veel fouten worden opgespoord. In plaats daarvan gebruikt u een kort .NET-programma om het nde getal van de Fibonacci-reeks te berekenen.

De Fibonacci-reeks bestaat uit een reeks cijfers die beginnen met de cijfers 0 en 1. Elk volgende cijfers is de som van de twee vorige cijfers. De volgorde is deze:

0, 1, 1, 2, 3, 5, 8, 13, 21...
  1. Open Program.cs door het te selecteren.

  2. Vervang de inhoud van Program.cs door de volgende code:

    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;
    }
    

    Notitie

    Deze code bevat een fout, die later in deze module wordt opgespoord. Het wordt niet aanbevolen om de code in essentiële Fibonacci-toepassingen te gebruiken tot deze fout is opgelost.

  3. Sla het bestand op door CTRL+S te selecteren voor Windows en Linux. Selecteer Cmd+S voor Mac.

  4. Laten we eens kijken hoe de bijgewerkte code werkt voordat we fouten opsporen. Voer het programma uit door de volgende opdracht in de terminal in te voeren:

    dotnet run
    

    Terminalvenster met gewijzigde programma-uitvoer.

  5. Het resultaat, 3, wordt weergegeven in de terminaluitvoer. Wanneer u dit Fibonacci-sequentiediagram raadpleegt waarin de op nul gebaseerde volgordepositie voor elke waarde tussen haakjes wordt weergegeven, ziet u dat het resultaat 5 had moeten zijn. Het wordt tijd vertrouwd te raken met het foutopsporingsprogramma en dit programma te corrigeren.

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

De problemen analyseren

  1. Start het programma door het tabblad Uitvoeren en foutopsporing aan de linkerkant te selecteren en vervolgens de knop Foutopsporing starten te selecteren. Mogelijk moet u eerst de knop Uitvoeren en foutopsporing selecteren en vervolgens het Program.cs-bestand selecteren.

    Schermafbeelding van de knop Foutopsporing starten in Visual Studio Code.

    Het programma zou snel voltooid moeten zijn. Dat is normaal omdat u nog geen onderbrekingspunten hebt toegevoegd.

  2. Als de console voor foutopsporing niet wordt weergegeven, selecteert u Ctrl+Shift+Y voor Windows en Linux of Cmd+Shift+Y voor Mac. U krijgt een aantal regels met diagnostische informatie te zien, aan het eind gevolgd door deze regels:

    ...
    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 regels bovenaan geven aan dat door de standaardinstellingen voor foutopsporing de optie Just My Code wordt ingeschakeld. Dit betekent dat het foutopsporingsprogramma alleen fouten in uw code opspoort en niet in de broncode voor .NET stapt, tenzij u deze modus uitschakelt. Zo kunt u zich richten op het opsporen van fouten in uw code.

Aan het einde van de uitvoer van de console voor foutopsporing ziet u dat er een 3 naar de console wordt geschreven. Vervolgens wordt het programma afgesloten met code 0. De afsluitcode 0 van een programma geeft meestal aan dat het programma is uitgevoerd en afgesloten zonder te zijn gecrasht. Er is echter een verschil tussen crashen en het retourneren van de juiste waarde. In dit geval hebben we het programma gevraagd om de vijfde waarde in de reeks van Fibonacci te berekenen:

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

De vijfde waarde in deze lijst is 5, maar door het programma is 3 geretourneerd. We gaan het foutopsporingsprogramma gebruiken om deze fout op te sporen en op te lossen.

Onderbrekingspunten en stapsgewijze uitvoering gebruiken

  1. Voeg een onderbrekingspunt toe door te klikken in de linkermarge op regel 1 op int result = Fibonacci(5);.

    Schermopname van de locatie van het onderbrekingspunt in de code.

  2. Start opnieuw met het opsporen van fouten. Het programma wordt uitgevoerd. De bewerking wordt onderbroken (de uitvoering wordt onderbroken) op regel 1 vanwege het onderbrekingspunt dat u hebt ingesteld. Gebruik de besturingselementen van het foutopsporingsprogramma om in de functie Fibonacci() te stappen.

    Schermopname van de knop Instappen.

Controleer de status van de variabelen

Inspecteer nu de waarden van de verschillende variabelen via het deelvenster Variabelen.

Schermopname van het deelvenster Variabelen.

  • Wat is de waarde die wordt weergegeven voor parameter n?
  • Wat zijn de waarden voor de lokale variabelen n1, n2 en sum op het moment dat de functie wordt uitgevoerd?
  1. Vervolgens gaat u naar de for-lus met behulp van het besturingselement Stap over van het foutopsporingsprogramma.

    Schermopname van de knop Overstappen.

  2. Ga door totdat u de eerste regel in de for-lus hebt bereikt, bij de met de volgende code:

    sum = n1 + n2;
    

Notitie

Het is u wellicht opgevallen dat u via de for(...) {} regel meerdere stappen in opdrachten moet uitvoeren. Deze situatie doet zich voor omdat er meerdere instructies op deze regel staan. Wanneer u een stap maakt, gaat u verder met de volgende instructie in uw code. Normaal gesproken is er één instructie per regel. Als dat niet het geval is, hebt u meerdere stappen nodig om door te gaan naar de volgende regel.

Nadenken over de code

Een belangrijk onderdeel van de foutopsporing is om even te stoppen en uw gezond verstand te gebruiken bij wat volgens u stukjes code (zowel functies als blokken, zoals lussen) eigenlijk doen. Het maakt niet uit als u het niet zeker weet, dat hoort bij het foutopsporingsproces. Maar door actief bezig te zijn met dit proces, kunt u fouten veel eerder leren opsporen.

Voordat we verder gaan: u herinnert zich wellicht dat de Fibonacci-reeks uit een reeks getallen bestaat die begint met de getallen 0 en 1. Elk volgend getal is de som van de twee vorige getallen.

Dat betekent dat:

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)

als u de definitie begrijpt en naar deze for-lus kijkt, u het volgende kunt afleiden:

  1. De lus telt van 2 tot n (het getal in de reeks van Fibonacci dat we zoeken).
  2. Als n kleiner is dan 2, wordt de lus nooit uitgevoerd. De instructie return aan het einde van de functie retourneert 0 als n 0 is en 1 als n 1 of 2 is. Dit zijn per definitie de nulde, eerste en tweede waarden in de Fibonacci-reeks.
  3. Het wordt interessanter als n groter is dan 2. In dergelijke gevallen wordt het huidige getal gedefinieerd als de som van de vorige twee getallen. Voor deze lus zijn n1 en n2 dus de vorige twee getallen en is sum het getal voor de huidige iteratie. Steeds wanneer de som van de twee vorige getallen wordt berekend en als sum wordt ingesteld, worden de getallen n1 en n2 bijgewerkt.

We hoeven dit verder niet te weten. We kunnen hier vertrouwen op het foutopsporingsprogramma. Maar het kan geen kwaad over de code na te denken om te zien of deze doet wat die moet doen, en om te weten wat er mis is als dat niet zo is.

De fout opsporen met onderbrekingspunten

Het doorlopen van uw code kan nuttig zijn, maar tijdrovend, vooral wanneer u met lussen of andere code werkt die herhaaldelijk wordt aangeroepen. In plaats van keer op keer in de lus te stappen, kunnen we een nieuw onderbrekingspunt instellen op de eerste regel van de lus.

Wanneer we dit doen, is het van belang de onderbrekingspunten zo strategisch mogelijk te plaatsen. We zijn vooral geïnteresseerd in de waarde van sum, omdat deze de huidige maximale Fibonacci-waarde vertegenwoordigt. Daarom zetten we het onderbrekingspunt op de regel nadatsum is ingesteld.

  1. Voeg een tweede onderbrekingspunt toe op regel 13.

    Schermopname waarin een tweede onderbrekingspunt wordt ingesteld.

    Notitie

    Als u merkt dat de u code blijft uitvoeren en vervolgens in een of twee regels instapt, kunt u uw onderbrekingspunten eenvoudig bijwerken naar meer efficiënte regels.

  2. Nu het onderbrekingspunt eenmaal goed in de lus is ingesteld, gebruikt u het besturingselement Doorgaan van het foutopsporingsprogramma om door te gaan tot het onderbrekingspunt wordt bereikt. Als we de lokale variabelen bekijken, zien we de volgende regels:

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

    Deze regels lijken correct. De eerste keer dat de lus wordt doorlopen, is de sum van de vorige twee waarden gelijk aan 1. In plaats van regel voor regel te doorlopen, kunnen we gebruikmaken van de onderbrekingspunten om direct naar de volgende uitvoering van de lus te gaan.

  3. Selecteer Doorgaan om het programma voort te zetten totdat het volgende onderbrekingspunt wordt bereikt, dus de volgende keer dat de lus wordt uitgevoerd.

    Notitie

    U hoeft zich geen zorgen te maken over het overslaan van de fout wanneer u Doorgaan gebruikt. U moet er rekening mee houden dat u vaak verschillende keren fouten moet opsporen in de code om het probleem te vinden. Wees niet te voorzichtig; het is vaak sneller om een paar keer door de code te lopen.

    Deze keer zien we de volgende waarden:

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

    Laten we dit eens bekijken. Lijken deze waarden nog steeds logisch? Het lijkt er wel op. Voor het derde Fibonacci-getal verwachten we dat de sum gelijk is aan 2, en dat is inderdaad zo.

  4. Selecteer Doorgaan om de lus opnieuw uit te voeren.

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

    Het ziet er opnieuw goed uit. De vierde waarde in de reeks moet 3 zijn.

  5. Op dit moment kunt u zich afvragen of de code direct al helemaal goed was en of u zich de fout hebt ingebeeld. Laten we de lus nog eens voor een laatste keer doorlopen. Selecteer nogmaals Doorgaan.

    Wacht eens even. Het programma is voltooid en heeft 3 afgedrukt. Dat klopt niet.

    Maar maakt u zich geen zorgen. We hebben er iets van geleerd. We weten nu zeker dat de code met de lus correct wordt uitgevoerd totdat i gelijk is aan 4, maar vervolgens wordt afgesloten voordat de uiteindelijke waarde wordt berekend. Ik begin wat ideeën te krijgen over waar de bug is. Ben je?

  6. Laten we nog één onderbrekingspunt instellen op regel 17, waarin het volgende wordt gelezen:

    return n == 0 ? n1 : n2;
    

    Met dit onderbrekingspunt kunnen we de status van het programma controleren voordat de functie wordt afgesloten. We hebben al geleerd wat we kunnen verwachten van onze vorige onderbrekingspunten op regel 1 en 13, zodat we ze kunnen wissen.

  7. Verwijder de vorige onderbrekingspunten op regel 1 en 13. U kunt dit doen door erop te klikken in de marge naast de regelnummers of door de selectievakjes voor onderbrekingspunten voor regel 1 en 13 in het deelvenster Onderbrekingspunten linksonder uit te schakelen.

    Schermopname van de onderbrekingspunten die worden vermeld in het deelvenster Onderbrekingspunten.

    We weten nu veel beter wat er gebeurt en we hebben een onderbrekingspunt ingesteld om verkeerd gedrag van ons programma te detecteren en zouden zo in staat moeten zijn om deze fout op te sporen.

  8. Start het foutopsporingsprogramma nog een laatste keer.

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

    Dat klopt ook niet. We hebben specifiek gevraagd om Fibonacci(5), maar we hebben Fibonacci(4) ontvangen. Deze functie retourneert n2 en elke iteratie van de lus berekent de waarde van sum en stelt n2 in op sum.

    Uit deze informatie en de vorige uitvoering van het foutopsporingsprogramma blijkt dat de lus wordt afgesloten wanneer i 4 is, en niet 5.

    Laten we de eerste regel van de for-lus eens nader bekijken.

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

    Oké, wacht eens even. Dat betekent dat het wordt afgesloten zodra de bovenkant van de for-lus ziet dat dat i niet langer minder is dan n. Dit betekent dat de code van de lus niet wordt uitgevoerd wanneer i gelijk is aan n. Het lijkt erop dat we de lus moeten uitvoeren tot i <= n:

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

    Met deze wijziging zou het bijgewerkte programma er als het volgende voorbeeld moeten uitzien:

    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. Stop de foutopsporingssessie als u dat nog niet hebt gedaan.

  10. Breng vervolgens de voorgaande wijziging aan in regel 10 en laat ons onderbrekingspunt op regel 17 staan.

  11. Start het foutopsporingsprogramma opnieuw. Wanneer we dit keer het onderbrekingspunt op regel 17 bereiken, zien we de volgende waarden:

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

    Hee. Dat lijkt er meer op. Goed gedaan. U hebt Fibonacci, Inc. uit de brand geholpen!

  12. Selecteer Doorgaan, enkel om te controleren of het programma de juiste waarde retourneert.

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

    Het programma retourneert de juiste uitvoer.

Het is u gelukt. U hebt fouten opgespoord in code die u niet hebt geschreven, met behulp van het .NET-foutopsporingsprogramma van Visual Studio Code.

In de volgende les leert u hoe u code schrijft waarin fouten gemakkelijker zijn op te sporen, met behulp van de functies voor logboekregistratie en tracering die in .NET zijn ingebouwd.