Debuggaus
Tässä harjoituksessa harjoitellaan debuggerin käyttöä Riderissa. Opetellaan seuraavat asiat:
- askeltaminen, askeltamien aliohjelman sisään (Step In) ja suorittaen aliohjelma kokonaisuutena (Step Over)
- keskeytyskohdan (Breakpoint) laittaminen ja ajaminen siihen
- lokaalien muuttujien (Locals) seuraaminen
Jos osaat jo debuggerin käytön hyvin tai haluat tehdä harjoituksen kotona, niin OK, siirry tekemään demoja. Mutta tee tämä harjoitus joka tapauksessa tällä viikolla ja käytä sen oppeja omissa demotehtävissä ja harkassa. Alla olevia asioita kysytään debuggausnäytteessä.
Versionhallinta (Git)
Jos et edellisessä ohjauksessa vielä tutustunut versionhallintaan, tee se nyt. Jos sinulla ei vielä ole omaa projektia kurssin etävarastossa, voit tehdä sen kohdan 3 ohjeilla. Tämän jälkeen kloonaa etävarasto omalle koneelle kohdan 6 ohjeilla.
1. Debuggaus
Lue monisteen luku 10.2 Debuggaus. Katso tehtävää tehdessä myös TIM-sivua debuggaus.
2. Askeltaminen debuggerissa ja lokaalit muuttujat
MacOS-käyttäjät! Näppäinoikotiet ovat oletuksena erilaiset, ne näkee Run
-menun alta. Opettele oman järjestelmäsi pikanäppäimet tai vaihda näppäinoikotiet alla olevan ohjeen mukaisesti.
[9.3.2023] Jos olet ottanut käyttöön Riderin uuden UI:n niin debuggaustila ei välttämättä toimi. Vaihda siis takaisin vanhaan UI:hin tai kokeile ehdotettuja korjauksia täältä.
Rider työkalupalkki:
Alla olevat näppäinkomennot ovat Visual Studiolle. Jos Riderissa valitsit näppäinoikoteiden (hot key, keyboard shortcut) asetuksiksi Visual Studion, niin silloin nämä toimivat myös Riderissa. Riderin näppäinoikotiet saa muutettua Configure -> Settings -> Keymap
tai File -> Settings -> Keymap
. HUOM! Vaikka tässä kohtaa puhutaan Visual Studiosta, tehtävä tehdään Riderilla, ei Visual Studiolla eikä varsinkaan Visual Studio Codella.
Toiminto | Näppäin Win | Näppäin Mac |
---|---|---|
Debug | F5 | ⌥ F5 |
Step Into | F11 | ⌘ F11 |
Step Over | F10 | F10 |
Resume | F5 | F5 |
Stop debugging | Shift+F5 | ⇧ F5 |
Macin painikkeet:
- ⌘ = cmd
- ⏎ = enter
- ⌥ = alt
- ⇧ = vaihto (shift)
Huomaa, että toiminnot voi myös ohjelmoida itse melkein mihin tahansa painikkeisiin.
Aluksi harjoitellaan askeltamista eri tavoin. Samoin opetellaan seuraamaan lokaaleja muuttujia.
Tee uusi Solution (vaikkapa nimelle Demo5) ja projekti 'Debuggaus' (
Console Application
tai vielä mieluumminConsoleMain
joka tuli mukana kun asensit Jypeli-projektimallit).Copy-pasteta sinne kaiken päälle seuraava sisältö:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LaskentaaMalli; public class LaskentaaMalli { public static void Main(string[] args) { double kanta = 5; double korkeus = 7; double ala; ala = KolmionAla(kanta, korkeus); System.Console.WriteLine(ala); System.Console.WriteLine("Valmis"); } public static double KolmionAla(double kanta, double korkeus) { double a = kanta * korkeus / 2; return a; } }
Laita keskeytyskohta riville
double kanta = 5;
. Keskeytyskohta laitetaan klikkaamalla koodi-ikkunan vasempaan reunaan halutun rivin kohdalla, vaalean harmaalla alueella. Sitten ota menusta Windows:Debug/Start Debugging
(jatkossaF5
), Mac:Run/Start Debugging
.
Jatkossa olevatF11
yms voivat vaihdella ja olla eri painikkeissa. Katso lyhenteetDebug
taiRun-menusta.
Ohjelma käynnistyy debuggaustilaan. Keltainen nuoli vasemmalla näyttää, mitä koodiriviä seuraavaksi suoritetaan.
Pysähdyttiin siis riville 11. Alhaalla näkyy 'Threads & Variables'-paneeli, jossa on paikalliset muuttujat. Listasta löytyy
args
-taulukon lisäksi,kanta
,korkeus
jaala
, joiden arvo on tällä hetkellä0.0
.Paina
Step into
(eli askella). Ollaan rivillä 12. Kanta-muuttujan arvoksi muuttui5.0
. Rider näyttää viimeksi muuttuneen arvon sinisellä.Paina niin kauan
Step into
, että tullaanKolmionAla
-aliohjelmakutsuun. Kun vielä kerran painatStep into
, hypätään riville 21KolmionAla
-aliohjelman sisään. Huomaatko, että Threads & Variables-paneeli muuttui, siellä ei enää ole samoja muuttujia kuinMain
-aliohjelmassa ollessamme (nyt emme enää ole Mainissa).Paina
Step into
niin kauan, että tullaanKolmionAla
-aliohjelman viimeiselle riville (rivi 24). Mitä luulet tapahtuvan kun vielä kerran painatStep into
(Win: F11)? Ennen painamista mieti, mihin keltainen nuoli seuraavaksi osoittaa.Klikkaa
Step into
niin kauan, että tullaanSystem.Console.WriteLine("Valmis");
-riville, ja tällöinStep over
(Win: F10). Mikäli klikkaat tässäStep into
, päädyt syvälle C#:n syövereihin. Pääset pois klikkaamallaStep Out
(Win: Shift + F11).
Paina
Step over
niin kauan että ohjelman suoritus päättyy.Kokeile tehdä sama homma uudestaan. Pysytkö kärryillä ohjelman suorittamisessa? Erityisen tärkeää on ymmärtää Threads & Variables-paneeli.
Jos haluat keskeyttää debuggauksen, paina
Stop debugging
(Win: Shift + F5).Aloita vielä kerran ohjelman suoritus painamalla kuten alussa (WIn: Alt + F11,
Mac Run/Start Debugging
). TullessasiKolmionAla
-aliohjelmakutsun kohdalle (rivi 14), painaStep over
(Windows: F10). Mitä tapahtui? Osaatko selittää toiminnon nimen "Step over" ja tapahtuneen välisen yhteyden?
3. Keskeytyskohta (break point)
Harjoitellaan keskeytyskohdan lisäämistä ja ajamista keskeytyskohtaan.
Tee äsken luomaasi solutioniin uusi projekti Debuggaus2 painamalla Solutionin nimen päällä hiiren oikeaa ja sitten
Add -> New Project
.Mikäli tiedoston nimeksi tuli
Program.cs
muuta se nimeksiJarjesta.cs
Kopioi alla oleva koodi ja liitä se juuri tekemäsi tiedoston sisällön tilalle
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Debuggaus { /// <summary> /// Harjoitellaan debuggerin käyttöä ja olioviitteitä. /// </summary> public class Jarjesta { /// <summary> /// Järjestetään taulukon 2 ekaa lukua järjetykseen. /// </summary> /// <param name="numerot">Järjestettävä taulukko.</param> public static void Jarjesta2(int[] numerot) { if (numerot[0] < numerot[1]) return; int t = numerot[0]; numerot[0] = numerot[1]; numerot[1] = t; } /// <summary> /// Vaihtaa, mutta ei toimi? /// </summary> /// <param name="a">1. luku</param> /// <param name="b">2. luku</param> public static void Jarjesta2(int a, int b) { if (a < b) return; int t = a; a = b; b = t; } /// <summary> /// Pääohjelmassa luodaan int-taulukko jossa 2 alkiota. /// Kutsutaan järjestä-aliohjelmia. /// </summary> /// <param name="args"></param> public static void Main(String[] args) { // 0 1 int[] luvut = { 34, 21 }; Console.WriteLine(luvut[0] + " " + luvut[1]); Jarjesta2(luvut[0], luvut[1]); Console.WriteLine(luvut[0] + " " + luvut[1]); Jarjesta2(luvut); Console.WriteLine(luvut[0] + " " + luvut[1]); } } }
Lue ohjelman kommentit läpi.
Laita keskeytyskohta (breakpoint) riville, jossa lukee
Jarjesta2(luvut)
. Keskeytyskohta laitetaan klikkaamalla koodi-ikkunan vasempaan reunaan, rivinumeron päälle.Laita ohjelma käyntiin debuggaustilassa
Debug
taiRun/Satrt debugging
(Windows: Alt-F5). Ohjelman ajo keskeytyy debuggaus-tilaan riville 49.Askella aliohjelman
Jarjesta2
sisään painamallaStep Into
(Win: F11).Avaa Threads & Variables -välilehti ruudun alareunasta.
numerot
-muuttujan kohdalla on pieni >-merkki (kolmio tai nuolenpää, josta valintaa voi suurentaa), josta voit tarkastella muuttujassa olevia tietoja.Askella aliohjelma läpi
Step Into
:lla (Win: F11).Kun palaat pääohjelmaan, klikkaa
Resume Program
(Win: F5), jolloin ohjelma ajaa itsensä loppuun saakka ilman askellusta.Poista nyt keskeytyskohta klikkaamalla punaista ympyrää.
Laita keskeytyskohta riville 47 ja debuggaa
Debug
(Win F5).Askella jälleen aliohjelman sisään, avaa Threads & Variables-välilehti ja tutki mitä tapahtuu.
Palatessasi pääohjelmaan klikkaa
Resume Program
(Win: F5) ja ohjelman suoritus menee loppuun saakka ilman askellusta.Yritä selvittää, miksi aliohjelmakutsu
Jarjesta2(luvut[0], luvut[1])
ei tee sitä mitä voisi kuvitella: pääohjelmassa tulostuu luvut alkuperäisessä järjestyksessä. Vinkki: monisteen luku 14. Olioiden ja alkeistietotyyppien erot.Tarvittaessa breakpointtiin voidaan asettaa ehtoja (Conditional Breakpoint). Tämä tapahtuu klikkaamalla breakpointtia hiiren oikealla ja valitsemalla Condition. Tämän tekemiseen kannattaa tutustua huolella, sillä debug-näytteessä sitä kysytään. Ks. esim. Ehdollisen keskeytyskohdan laittaminen
4 String ja StringBuilder olioiden ero aliohjelmakutsussa
Tee samaan solutioniin uusi projekti
Debuggaus3
.Tutki koodia:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Olioviitteita { /// <summary> /// Harjoitellaan olioviitteiden käyttöä. /// </summary> public class Olioviitteita { /// <summary> /// Luodaan String-olio ja StringBuilder-olio, ja kutsutaan aliohjelmia /// välittäen niille luodut oliot, ja katsotaan mitä tapahtuu. /// </summary> /// <param name="args"></param> public static void Main(string[] args) { StringBuilder mj1 = new StringBuilder("Janne"); MuutaMerkkiSB(mj1); Console.WriteLine(mj1); // Mitä tulostuu? Miksi?? String mj2 = "Janne"; MuutaMerkki(mj2); Console.WriteLine(mj2); // Mitä tulostuu? Miksi?? } /// <summary> /// Lisätään annetun StringBuilder-merkkijonon perään sana. /// </summary> /// <param name="a">Annettu StringBuilder-merkkijono.</param> public static void MuutaMerkkiSB(StringBuilder a) { a.Append(" Seppänen"); } /// <summary> /// Lisätään annetun String-merkkijonon perään sana. /// </summary> /// <param name="a">Annettu String-merkkijono.</param> public static void MuutaMerkki(String a) { a = a + " Seppänen"; } } }
Älä vielä liitä koodia Rideriin.
Lue koodi tarkasti läpi.
Mieti, mitä tulostuu riveillä joissa lukee
Mitä tulostuu?
. Onko tulostuksissa jotain eroa, ja jos on, miksi?Kopioi lopuksi koodi Rideriin ja tarkista asia.
Keskustele vieruskaverin kanssa, miksi ohjelma käyttäytyi niin kuin käyttäytyi.
5. Harjoitustyö
- Olethan tehnyt ja palauttanut harjoitustyön suunnitelman?
6. Demotehtävät
- Tee demotehtäviä. Käytä debuggeria jos on ongelmia!
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.