Debuggen voor absolute beginners
Zonder uitzondering doet de code die we als softwareontwikkelaars schrijven niet altijd wat we verwachten. Soms doet het iets heel anders! Wanneer het onverwachte gebeurt, is de volgende taak om erachter te komen waarom, en hoewel we misschien geneigd zijn om urenlang naar onze code te staren, is het eenvoudiger en efficiënter om een foutopsporingsprogramma of foutopsporingsprogramma te gebruiken.
Een foutopsporingsprogramma is helaas niet iets dat magisch alle problemen of 'bugs' in onze code kan onthullen. Foutopsporing betekent dat u uw code stap voor stap uitvoert in een hulpprogramma voor foutopsporing, zoals Visual Studio, om het exacte punt te vinden waar u een programmeerfout hebt gemaakt. Vervolgens begrijpt u welke correcties u moet aanbrengen in uw code en hulpprogramma's voor foutopsporing, kunt u vaak tijdelijke wijzigingen aanbrengen, zodat u het programma kunt blijven uitvoeren.
Het gebruik van een foutopsporingsprogramma is ook een vaardigheid die tijd en oefening kost om te leren, maar uiteindelijk een fundamentele taak is voor elke softwareontwikkelaar. In dit artikel introduceren we de belangrijkste principes van foutopsporing en geven we tips om u op weg te helpen.
Verhelder het probleem door uzelf de juiste vragen te stellen
Het helpt om het probleem te verduidelijken dat u tegenkomt voordat u het probeert op te lossen. We verwachten dat er al een probleem is opgetreden in uw code, anders zou u hier niet proberen te achterhalen hoe u fouten kunt opsporen. Voordat u begint met foutopsporing, moet u er dus voor zorgen dat u het probleem hebt geïdentificeerd dat u probeert op te lossen:
Wat verwachtte u van uw code?
Wat is er gebeurd?
Als er een fout (uitzondering) optreedt tijdens het uitvoeren van uw app, kan dit een goede zaak zijn. Een uitzondering is een onverwachte gebeurtenis die optreedt bij het uitvoeren van code, meestal een fout van een bepaald type. Met een hulpprogramma voor foutopsporing kunt u naar de exacte plaats in uw code gaan waar de uitzondering is opgetreden en kunt u mogelijke oplossingen onderzoeken.
Als er iets anders is gebeurd, wat is het symptoom van het probleem? Vermoedt u al waar dit probleem is opgetreden in uw code? Als uw code bijvoorbeeld tekst weergeeft, maar de tekst onjuist is, weet u dat uw gegevens slecht zijn of dat de code waarmee de weergavetekst is ingesteld, een fout heeft. Door de code in een foutopsporingsprogramma te doorlopen, kunt u elke wijziging in uw variabelen bekijken om precies te ontdekken wanneer en hoe onjuiste waarden worden toegewezen.
Uw veronderstellingen onderzoeken
Voordat je een bug of een fout gaat onderzoeken, denk aan de veronderstellingen die je deden verwachten een bepaald resultaat te zien. Verborgen of onbekende aannames kunnen het moeilijk maken een probleem te identificeren, zelfs wanneer u direct naar de oorzaak ervan in een debugger kijkt. Misschien hebt u een lange lijst met mogelijke veronderstellingen! Hier volgen enkele vragen om uzelf te vragen om uw veronderstellingen uit te dagen.
Gebruikt u de juiste API (dat wil zeggen het juiste object, de juiste functie, methode of eigenschap)? Een API die u gebruikt, doet mogelijk niet wat u ervan vindt. (Nadat u de API-aanroep in het foutopsporingsprogramma hebt bekeken, kan het oplossen ervan een trip naar de documentatie vereisen om de juiste API te identificeren.)
Gebruikt u een API correct? Misschien hebt u de juiste API gebruikt, maar deze niet op de juiste manier gebruikt.
Bevat uw code typfouten? Sommige typefouten, zoals een eenvoudige spelfout in een variabelenaam, kunnen moeilijk te zien zijn, vooral bij het werken met talen waarvoor geen variabelen hoeven te worden gedeclareerd voordat ze worden gebruikt.
Hebt u een wijziging aangebracht in uw code en ervan uitgegaan dat deze niet is gerelateerd aan het probleem dat u ziet?
Had u verwacht dat een object of variabele een bepaalde waarde (of een bepaald type waarde) bevat die verschilt van wat er echt is gebeurd?
Weet u wat de bedoeling van de code is? Het is vaak moeilijker om fouten op te sporen in de code van iemand anders. Als het niet uw code is, is het mogelijk dat u tijd moet besteden aan het leren wat de code doet voordat u effectief fouten kunt opsporen.
Fooi
Begin bij het schrijven van code klein en begin met code die werkt. (Goede voorbeeldcode is hier nuttig.) Soms is het eenvoudiger om een grote of gecompliceerde set code op te lossen door te beginnen met een klein stukje code dat de kerntaak laat zien die u probeert te bereiken. Vervolgens kunt u code incrementeel wijzigen of toevoegen, zodat u op elk punt op fouten kunt testen.
Door uw veronderstellingen te ondervragen, kunt u de tijd beperken die nodig is om een probleem in uw code te vinden. U kunt ook de tijd verminderen die nodig is om een probleem op te lossen.
Doorloop uw code in de foutopsporingsmodus om te achterhalen waar het probleem is opgetreden
Wanneer u normaal gesproken een app uitvoert, ziet u fouten en onjuiste resultaten pas nadat de code is uitgevoerd. Een programma kan ook onverwacht worden beëindigd zonder u te vertellen waarom.
Wanneer u een app uitvoert in een foutopsporingsprogramma, ook wel foutopsporingsmodusgenoemd, controleert het foutopsporingsprogramma alles wat er gebeurt terwijl het programma wordt uitgevoerd. U kunt de app ook op elk gewenst moment onderbreken om de status ervan te onderzoeken en vervolgens de coderegel per regel doorlopen om alle details te bekijken terwijl deze zich voordoet.
In Visual Studio gaat u de foutopsporingsmodus in met behulp van F5 (of de Foutopsporing>Debugging starten menuopdracht of de knop Foutopsporing starten knop op de werkbalk Foutopsporing). Als er uitzonderingen optreden, gaat u met de Uitzonderingshulpfunctie van Visual Studio naar het exacte punt waar de uitzondering is opgetreden en vindt u andere nuttige informatie. Zie Technieken en hulpprogramma's voor foutopsporingvoor meer informatie over het afhandelen van uitzonderingen in uw code.
Als u geen uitzondering krijgt, hebt u waarschijnlijk een goed idee waar u naar het probleem in uw code kunt zoeken. In deze stap gebruikt u onderbrekingspunten met het foutopsporingsprogramma om uzelf een kans te geven om uw code zorgvuldiger te onderzoeken. Onderbrekingspunten zijn de meest elementaire en essentiële functie van betrouwbare foutopsporing. Een onderbrekingspunt geeft aan waar Visual Studio de actieve code moet onderbreken, zodat u de waarden van variabelen, of het gedrag van het geheugen, kunt bekijken in de volgorde waarin code wordt uitgevoerd.
In Visual Studio kunt u snel een onderbrekingspunt instellen door in de linkermarge naast een regel code te klikken. Of plaats de cursor op een lijn en druk op F9.
Om deze concepten te illustreren, nemen we u door een aantal voorbeeldcode die al verschillende bugs bevat. We gebruiken C#, maar de foutopsporingsfuncties zijn van toepassing op Visual Basic, C++, JavaScript, Python en andere ondersteunde talen. Er is ook voorbeeldcode voor Visual Basic opgegeven, maar schermopnamen bevinden zich in C#.
Een voorbeeld-app maken (met een aantal bugs)
Vervolgens maakt u een toepassing met een aantal bugs.
Je moet Visual Studio hebben geïnstalleerd en de .NET-desktopontwikkeling-workload geïnstalleerd hebben.
Als u Visual Studio nog niet hebt geïnstalleerd, gaat u naar de Visual Studio-downloadpagina pagina om deze gratis te installeren.
Als u de workload wilt installeren maar Visual Studio al hebt, selecteert u Tools>Hulpprogramma's en onderdelen ophalen. Het installatieprogramma van Visual Studio wordt gestart. Kies de .NET-desktopontwikkelingswerklast en selecteer vervolgens Wijzigen.
Open Visual Studio.
Kies in het startvenster Een nieuw project maken. Typ console in het zoekvak, selecteer C#- of Visual Basic- als taal en kies vervolgens Console-app voor .NET. Kies Volgende. Typ ConsoleApp_FirstApp als projectnaam en selecteer Volgende.
Als u een andere projectnaam gebruikt, moet u de waarde van de naamruimte wijzigen zodat deze overeenkomt met de projectnaam wanneer u de voorbeeldcode kopieert.
Kies het aanbevolen doelframework of .NET 8 en selecteer vervolgens Aanmaken.
Als u de Console-app projectsjabloon voor .NET niet ziet, gaat u naar Tools>Hulpprogramma's en onderdelen ophalen, waarmee het installatieprogramma van Visual Studio wordt geopend. Kies de .NET-desktopontwikkelingswerklast en selecteer vervolgens Wijzigen.
Visual Studio maakt het consoleproject, dat wordt weergegeven in Solution Explorer in het rechterdeelvenster.
Vervang in Program.cs (of Program.vb) alle standaardcode door de volgende code. (Selecteer eerst het juiste taaltabblad, C# of Visual Basic.)
using System; using System.Collections.Generic; namespace ConsoleApp_FirstApp { class Program { static void Main(string[] args) { Console.WriteLine("Welcome to Galaxy News!"); IterateThroughList(); Console.ReadKey(); } private static void IterateThroughList() { var theGalaxies = new List<Galaxy> { new Galaxy() { Name="Tadpole", MegaLightYears=400, GalaxyType=new GType('S')}, new Galaxy() { Name="Pinwheel", MegaLightYears=25, GalaxyType=new GType('S')}, new Galaxy() { Name="Cartwheel", MegaLightYears=500, GalaxyType=new GType('L')}, new Galaxy() { Name="Small Magellanic Cloud", MegaLightYears=.2, GalaxyType=new GType('I')}, new Galaxy() { Name="Andromeda", MegaLightYears=3, GalaxyType=new GType('S')}, new Galaxy() { Name="Maffei 1", MegaLightYears=11, GalaxyType=new GType('E')} }; foreach (Galaxy theGalaxy in theGalaxies) { Console.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears + ", " + theGalaxy.GalaxyType); } // Expected Output: // Tadpole 400, Spiral // Pinwheel 25, Spiral // Cartwheel, 500, Lenticular // Small Magellanic Cloud .2, Irregular // Andromeda 3, Spiral // Maffei 1, 11, Elliptical } } public class Galaxy { public string Name { get; set; } public double MegaLightYears { get; set; } public object GalaxyType { get; set; } } public class GType { public GType(char type) { switch(type) { case 'S': MyGType = Type.Spiral; break; case 'E': MyGType = Type.Elliptical; break; case 'l': MyGType = Type.Irregular; break; case 'L': MyGType = Type.Lenticular; break; default: break; } } public object MyGType { get; set; } private enum Type { Spiral, Elliptical, Irregular, Lenticular} } }
Onze bedoeling voor deze code is om de galaxynaam, de afstand tot het melkwegstelsel en het galaxytype allemaal in een lijst weer te geven. Als u fouten wilt opsporen, is het belangrijk dat u de intentie van de code begrijpt. Dit is de indeling voor één regel in de lijst die we in de uitvoer willen weergeven:
sterrenstelsel naam, afstand, sterrenstelseltype.
De app uitvoeren
Druk op F5 of op de knop Start Debugging, aangeduid met het in de foutopsporingswerkbalk boven de code-editor.
De app wordt gestart en er worden geen uitzonderingen weergegeven door het foutopsporingsprogramma. De uitvoer die u in het consolevenster ziet, is echter niet wat u verwacht. Dit is de verwachte uitvoer:
Tadpole 400, Spiral
Pinwheel 25, Spiral
Cartwheel, 500, Lenticular
Small Magellanic Cloud .2, Irregular
Andromeda 3, Spiral
Maffei 1, Elliptical
Maar in plaats daarvan ziet u deze uitvoer:
Tadpole 400, ConsoleApp_FirstApp.GType
Pinwheel 25, ConsoleApp_FirstApp.GType
Cartwheel, 500, ConsoleApp_FirstApp.GType
Small Magellanic Cloud .2, ConsoleApp_FirstApp.GType
Andromeda 3, ConsoleApp_FirstApp.GType
Maffei 1, 11, ConsoleApp_FirstApp.GType
Als we kijken naar de uitvoer en onze code, weten we dat GType
de naam is van de klasse waarin het galaxy-type wordt opgeslagen. We proberen het werkelijke galaxytype (zoals 'Spiraal'), niet de klassenaam weer te geven.
Fouten opsporen in de app
Wanneer de app nog steeds wordt uitgevoerd, voegt u een onderbrekingspunt in.
Klik in de
foreach
lus met de rechtermuisknop naast de methodeConsole.WriteLine
om het contextmenu op te halen en selecteer Onderbrekingspunt invoegen>Onderbrekingspunt invoegen in het vervolgmenu.foreach (Galaxy theGalaxy in theGalaxies) { Console.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears + ", " + theGalaxy.GalaxyType); }
Wanneer u het onderbrekingspunt instelt, wordt er een rode stip weergegeven in de linkermarge.
Als u een probleem in de uitvoer ziet, begint u met foutopsporing door te kijken naar de voorgaande code waarmee de uitvoer in het foutopsporingsprogramma wordt ingesteld.
Selecteer het pictogram Opnieuw opstarten
knop in de foutopsporingswerkbalk (Ctrl + Shift + F5).
De app wordt gepauzeerd bij het onderbrekingspunt dat u hebt ingesteld. De gele markering geeft aan waar het foutopsporingsprogramma is onderbroken (de gele coderegel is nog niet uitgevoerd).
Beweeg de muisaanwijzer over de variabele
GalaxyType
aan de rechterkant en vouw vervolgens links van het sleutelpictogramtheGalaxy.GalaxyType
uit. U ziet datGalaxyType
een eigenschap bevatMyGType
en dat de eigenschapswaarde is ingesteld opSpiral
.'Spiraal' is eigenlijk de juiste waarde die je verwachtte te printen op de console! Het is dus een goed begin dat u toegang hebt tot de waarde in deze code tijdens het uitvoeren van de app. In dit scenario gebruiken we de onjuiste API. Laten we eens kijken of u dit kunt oplossen tijdens het uitvoeren van code in het foutopsporingsprogramma.
Terwijl u aan het debuggen bent, plaatst u de cursor aan het einde van
theGalaxy.GalaxyType
en wijzigt u deze intheGalaxy.GalaxyType.MyGType
in dezelfde code. Hoewel u de bewerking kunt doorvoeren, ziet u in de code-editor een fout (rode golvende lijn). (In Visual Basic wordt de fout niet vertoond en werkt deze code-sectie.)Druk op F11 (Fouten opsporen>Stap in of de knop Stap in in de werkbalk Foutopsporing) om de huidige coderegel uit te voeren.
F11 voert de debugger één instructie tegelijk uit (en voert code uit). F10 (Step Over) is een vergelijkbare opdracht en beide zijn handig bij het gebruik van het foutopsporingsprogramma.
Als u probeert de debugger verder te zetten, verschijnt het dialoogvenster Hot Reload, dat aangeeft dat bewerkingen niet kunnen worden gecompileerd.
Het dialoogvenster Bewerken en Doorgaan wordt weergegeven, waarmee wordt aangegeven dat bewerkingen niet kunnen worden gecompileerd.
Notitie
Voor foutopsporing van de Visual Basic-voorbeeldcode slaat u de volgende stappen over totdat u wordt gevraagd op het pictogram Opnieuw opstarten
knop.
Selecteer bewerken in het berichtvak Dynamisch opnieuw laden of Bewerken en Doorgaan. U ziet nu een foutbericht in het venster Foutenlijst. De fout geeft aan dat de
'object'
geen definitie voorMyGType
bevat.Hoewel we elke galaxy instellen met een object van het type
GType
(die de eigenschapMyGType
heeft), herkent het foutopsporingsprogramma hettheGalaxy
object niet als een object van het typeGType
. Wat gebeurt er? U wilt alle code bekijken waarmee het galaxy-type wordt ingesteld. Als u dit doet, ziet u dat deGType
klasse zeker een eigenschap vanMyGType
heeft, maar dat er iets niet klopt. Het foutbericht overobject
blijkt de aanwijzing te zijn; voor de taal-interpreter lijkt het type een object van het typeobject
te zijn in plaats van een object van het typeGType
.Tijdens het doorzoeken van de code met betrekking tot het instellen van het galaxietype, ontdekt u dat de eigenschap
GalaxyType
van de klasseGalaxy
is opgegeven alsobject
in plaats vanGType
.public object GalaxyType { get; set; }
Wijzig de voorgaande code als volgt:
public GType GalaxyType { get; set; }
Selecteer het pictogram Opnieuw opstarten
knop in de foutopsporingswerkbalk (Ctrl + Shift + F5) om de code opnieuw te compileren en opnieuw op te starten.
Wanneer het foutopsporingsprogramma wordt onderbroken op
Console.WriteLine
, kunt u de muisaanwijzer overtheGalaxy.GalaxyType.MyGType
bewegen en zien dat de waarde juist is ingesteld.Verwijder het onderbrekingspunt door te klikken op de onderbrekingspuntcirkel in de linkermarge (of klik met de rechtermuisknop en kies onderbrekingspunt>Onderbrekingspunt verwijderen) en druk vervolgens op F5 om door te gaan.
De app draait en de uitvoer wordt weergegeven. Het ziet er goed uit, maar je ziet één ding. U had verwacht dat de Small Magellanic Cloud als een onregelmatig sterrenstelsel in de console-uitvoer zou verschijnen, maar het toont helemaal geen type sterrenstelsel.
Tadpole 400, Spiral Pinwheel 25, Spiral Cartwheel, 500, Lenticular Small Magellanic Cloud .2, Andromeda 3, Spiral Maffei 1, Elliptical
Stel een onderbrekingspunt in op deze regel code vóór de
switch
instructie (vóór deSelect
-instructie in Visual Basic).public GType(char type)
Deze code is waar het galaxy-type is ingesteld, dus we willen het nader bekijken.
Selecteer het pictogram Opnieuw opstarten
-knop in de foutopsporingswerkbalk (Ctrl + Shift + F5) om opnieuw te starten.
Het foutopsporingsprogramma pauzeert op de coderegel waar u het onderbrekingspunt instelt.
Beweeg de muisaanwijzer over de variabele
type
. U ziet een waarde vanS
(na de tekencode). Je bent geïnteresseerd in een waarde vanI
, omdat je weet dat dat een onregelmatig galaxietype is.Druk op F5- en plaats de muisaanwijzer nogmaals op de variabele
type
. Herhaal deze stap totdat u een waarde vanI
in de variabeletype
ziet.Druk nu op F11 (Debuggen>Binnenstappen).
Druk op F11 totdat u stopt op een coderegel in de
switch
-instructie voor de waarde 'I' (Select
-instructie voor Visual Basic). Hier ziet u een duidelijk probleem dat het gevolg is van een typefout. U had verwacht dat de code verder moest gaan naar de locatie waarMyGType
als een onregelmatig galaxytype wordt ingesteld, maar het foutopsporingsprogramma slaat deze code volledig over en onderbreekt dedefault
sectie van deswitch
-instructie (Else
instructie in Visual Basic).Als u de code bekijkt, ziet u een typefout in de
case 'l'
instructie. Het moetcase 'I'
zijn.Selecteer de code voor
case 'l'
en vervang deze doorcase 'I'
.Verwijder het onderbrekingspunt en selecteer vervolgens de knop Opnieuw opstarten om de app opnieuw op te starten.
De fouten zijn nu opgelost en u ziet de uitvoer die u verwacht.
Druk op een willekeurige toets om de app te voltooien.
Samenvatting
Wanneer u een probleem ziet, gebruikt u het foutopsporingsprogramma en stapopdrachten zoals F10 en F11 om de coderegio met het probleem te vinden.
Notitie
Als het lastig is om de coderegio te identificeren waar het probleem optreedt, stelt u een onderbrekingspunt in code in die wordt uitgevoerd voordat het probleem zich voordoet en gebruikt u vervolgens stapopdrachten totdat u het probleemmanifest ziet. U kunt ook tracepoints gebruiken om berichten te registreren bij het venster Uitvoer. Door te kijken naar vastgelegde berichten (en te weten welke berichten nog niet zijn geregistreerd!), kunt u vaak de coderegio isoleren met het probleem. Mogelijk moet u dit proces meerdere keren herhalen om het te beperken.
Wanneer u de coderegio met het probleem vindt, gebruikt u het foutopsporingsprogramma om te onderzoeken. Als u de oorzaak van een probleem wilt vinden, inspecteert u de probleemcode tijdens het uitvoeren van uw app in het foutopsporingsprogramma:
Inspecteer de variabelen en controleer of ze het juiste type waarden bevatten. Als u een ongeldige waarde vindt, zoekt u uit waar de ongeldige waarde is ingesteld (om te bepalen waar de waarde is ingesteld, moet u het foutopsporingsprogramma mogelijk opnieuw starten, kijken naar de aanroepstackof beide).
Controleer of uw toepassing de code uitvoert die u verwacht. (In de voorbeeldtoepassing verwachtten we bijvoorbeeld dat de code voor de
switch
-instructie het galaxytype instelt op Onregelmatig, maar de app heeft de code overgeslagen vanwege de typfout.)
Fooi
U gebruikt een foutopsporingsprogramma om fouten te vinden. Een tool voor foutopsporing kan fouten alleen voor u vinden als deze de intentie van uw code kent. Een hulpprogramma kan alleen de intentie van uw code kennen als u, de ontwikkelaar, die intentie uitdrukt. Het schrijven van eenheidstests is hoe u dat doet.
Volgende stappen
In dit artikel hebt u enkele algemene concepten voor foutopsporing geleerd. Vervolgens kunt u meer leren over het foutopsporingsprogramma.