Debuggaus

Tässä esitellään lyhyesti debuggauksen tarkoitus ja Visual Studion tärkeimmät debuggaustoiminnot. Vaikka jokaisessa kehitysympäristössä on omat debuggaustapansa, ovat periaatteet hyvin pitkälti yhteisiä eri ympäristöjen välillä. Kuvat ovat hieman vanhemmasta Visual Studiosta mutta periaatteet ovat samoja edelleen.

Tämä sivu sisältää täydennyksiä monisteen lukuun 10.2 Debuggaus.

Tämä sivu kuuluu myös Ohjelmointi 1 -kurssin debuggausnäytteen esitietoihin. Lue tämä sivu huolellisesti ennen debuggausnäytteeseen tulemista. Syksyn kurssilla debuggausta on harjoiteltu myös pääteohjauksessa 5.

1. Miksi pitää debugata?

Jos ohjelmassa on jotakin vikaa (ohjelmointivirhe eli bug), debuggeri on usein helpoin vaihtoehto vian löytämiseksi (virheenjäljitys eli debug). Ohjelmaa voi debugata myös lisäämällä sinne tänne ylimääräisiä tulostuslauseita, mutta debuggerin avulla ohjelmakoodiin ei tarvitse tehdä muutoksia. Debuggerin avulla ohjelma voidaan myös pysäyttää haluttuun kohtaan ja tutkia muuttujien senhetkisiä arvoja, mahdollisesti jopa muuttaa niitä ennen kuin ohjelman suorittamista taas jatketaan. Tämä ei ole mahdollista tulostuslause-tyylisessä debuggauksessa.

Ohjelmointia opetellessa debuggeri on myös oiva väline askeltaa silmukoita, ehtoja ja aliohjelmia ja näin havainnollistaa ohjelman kulkua itselleen.

2. Debuggaustila VS:ssä

MAC HUOM!. Alla olevissa ohjeissa on aina menuista puhuttaessa Debug -jotakin. VS for Macissa vastaava menu on Run. Lisäksi Macissa pikanäppäimet ovat oletuksena erit, ne näkee sieltä Run-menun alta. Opettele oman järjestelmäsi pikanäppäimet.

Työkalupalkki Windowsissa:

Työkalupalkki Macissa:


Toiminto Menu Win Näppäin Win Menu Mac Näppäin Mac
Start debugging Debug F5 Run ⌘⏎
Step Into Debug F11 Run ⇧⌘I
Step Over Debug F10 Run ⇧⌘O
Continue Debug F5 Run ⌘⏎
Stop debugging Debug Shift+F5 Run ⇧⌘⏎

Mac painike:

  • ⌘ = cmd
  • ⏎ = enter
  • ⌥ = alt
  • ⇧ = vaihtonäppäin

Huomaa että toiminnot voi ohjelmoida itse melkein mihin tahansa painikkeisiin.

Visual Studiossa debuggaustila käynnistetään painamalla F5. Tällöin ohjelma voidaan milloin tahansa pysäyttää, tai lisätä ohjelmakoodiin keskeytyskohta (breakpoint) ja näin pysäyttää ohjelma haluttuun kohtaan. Jos ohjelmassa ei ole yhtään breakpointtia, vaikuttaa debugtilassa ajo samanlaiselta kuin "normaalissa" (release-tila, ei-debuggaus) suoritustilassa. Release-ajo saadaan käyntiin painamalla Ctrl-F5.

Tarkasti ottaen debug- (F5) ja release-käännökset (Ctrl-F5) tehdään hieman eri tavalla, ja release-käännetty koodi optimoidaan käytännössä hieman nopeammaksi. Tämän kurssin kannalta nopeuserolla ei kuitenkaan ole merkitystä.

Debug-tila on kätevä myös pelien ongelmia selvitettäessä. Laita peli käyntiin debuggaustilassa (F5), ja kun pelioliot ovat tulleet näytölle käydään lisäämässä epäiltyyn ongelmapaikkaan koodiin breakpoint.

Samoin jos ohjelma tuntuu olevan totaalisen jumissa, voidaan sen ajo pysäyttää ja katsoa, missä kohti ohjelmaa ollaan menossa ja näin ehkä voidaan ratkaista, mistä ohjelman "jumi" johtuu.

3. Debuggaustoiminnot

# breakpoint

3.1 Keskeytyskohta, breakpoint

Voit laittaa ohjelmaan keskeytyskohdan eli ''breakpointin'', jonka tarkoituksena on keskeyttää ohjelman suoritus haluttuun kohtaan. Toisin sanoen, ohjelma suoritetaan alusta siihen saakka, kunnes tullaan keskeytyskohtaan, johon suoritus sitten pysähtyy.

Vie hiiri harmaalle alueelle ikkunan vasempaan reunaan, jolloin kursori muuttuu vasemmalle päin osoittavaksi.

Aseta breakpoint
Aseta breakpoint

Paina hiirellä keskeytyskohta haluamaasi kohtaan.

Aseta breakpoint 2
Aseta breakpoint 2

3.2 Debuggaustilan käynnistäminen

Ohjelma käynnistyy debuggaustilaan painamalla F5 tai valikosta Debug -> Start debugging. Tällöin ohjelman suoritus "pysähtyy" ensimmäiseen asettamaasi keskeytyskohtaan.

Debug1
Debug1

Huomaa, että keskeytyskohdan osoittaman punaisen pallon päällä on nyt myös keltainen nuoli, joka näyttää seuraavaksi suoritettavan rivin. Toisin sanoen, ohjelman alkuosa on suoritettu rivi riviltä normaaliin tapaan, ja suoritus pysähtyy keskeytyskohtaan siten, että ''seuraavaksi'' suoritusvuorossa on tutkittava rivi, jolle breakpoint on asetettu. Korostan: tätä keltaisen nuolen osoittamaa asiaa ''ei'' ole vielä suoritettu.

On mahdollista suorittaa ohjelma myös ilman debuggausta (Ctrl + F5 tai Debug -> Start without debugging). Tällöin keskeytyskohdat jätetään huomiotta. Toisaalta myös esimerkiksi poikkeuksia (exceptions) ei käsitellä Visual Studion avulla, vaan ohjelmat voivat kaatua hallitsemattomasti.

# askellus

3.3 Askellus (Step into, Step over)

Koodia voidaan askeltaa rivi kerrallaan. Tällöin ohjelman suoritus etenee debuggaustilassa rivi kerrallaan eteenpäin. Askellukseen on kaksi erilaista tapaa

  • Step into (F11), askelletaan myös kutsuttavien aliohjelmien koodi riveittäin
  • Step over (F10), aliohjelmakutsujen koodi suoritetaan kerralla ilman askellusta, eli tavallaan hypätään aliohjelman yli

3.4 Continue

Continue-toiminto jatkaa ohjelman suorittamista normaaliin tapaan. Mikäli ohjelmassa on myöhemmin keskeytyskohta, ohjelman suoritus keskeytyy siihen.

3.5 Debuggaustilan lopettaminen (ohjelman ajon lopettaminen)

Debuggauksen voi lopettaa painamalla Shift + F5 tai valikosta Debug -> Stop debugging.

3.6 Muuttuja-arvot (locals)

Debuggaus‐näkymässä Locals-paneelissa näkyy kaikki tällä hetkellä näkyvillä olevat muuttujat (paikalliset, eli lokaalit muuttujat) ja niiden arvot. Vinkki: Jos Locals-paneeli vahingossa häviää näkyviltä, saat sen takaisin debuggaustilassa Debug-valikosta.

Locals-paneelissa voi myös muokata muuttujien arvoja ajonaikaisesti. Esimerkiksi muuttujan "luku"-arvoa voi muokata kaksoisklikkaamalla Value-sarakkeen kohdalta numeroa ja kirjoittamalla uuden luvun vanhan tilalle. Tämän jälkeen kannattaa painaa Enteriä, jotta editori ottaa muutoksen.

JetBrains Rider: muuttujan arvoa voi muokata locals-ikkunassa painamalla F2 tai oikeaklikkaamalla ja valitsemalla Set Value. -JuhoK

14 Oct 20

3.7 Call stack, kutsupino

Jos saa ison ohjelman tutkittavakseen ja pitää korjata jotakin kohtaa eikä tiedä mistä ko. kohtaan tullaan, niin jälleen debuggeri on avuksi. Laita keskeytyskohta (breakpoint) tutkittavaan kohtaan, sitten ohjelma käyntiin (paina F5) ja kun ohjelma pysähtyy laittamaasi keskeytyskohtaan, niin kutsupinosta (Call Stack) voidaan katsoa reitti, mistä pysäytyskohtaan on päädytty.

Debug2
Debug2
# watch

3.8 Watch

Watch-paneeli on kuten Locals-paneeli, mutta käyttäjä määrittelee itse, mitä muuttujia haluaa seurata suorituksen aikana. Yksittäisten muuttujien lisäksi Watch-paneeliin voi lisätä lausekkeita, esimerkiksi taulukko[i] > suurin (tuottaisi true tai false).

  1. Aseta keskeytyskohta haluamaasi paikkaan ja aloita debuggaus.
  2. Etsi koodista se muuttuja (tai lauseke), jonka tilaa haluat tarkkailla ajon aikana. Valitse se (maalaamalla esimerkiksi hiirellä), klikkaa sitten hiiren oikealla ja valitse Add Watch. (Alla olevassa kuvassa lisätään suurin-muuttuja watch-paneeliin.
Watch1
Watch1
Watch2
Watch2
  1. Voit lisätä eri "watcheja" haluamasi määrän. Alla lisätään myös i, taulukko[i] ja taulukko[i] > suurin watch-paneeliin.

Huomaa, että watch-paneeliin lisäämäsi muuttuja (tai lauseke) ei välttämättä ole olemassa (ts. ei ole luotu tai ei "näy" sillä hetkellä), joten luonnollisestikaan tilaa ei voida tällöin tutkia. Alla olevassa kuvassa suoritus on menossa vasta rivillä 12.

Watch3
Watch3

Tässä esimerkissä i, taulukko[i] ja taulukko[i] > suurin ovat paikallisia muuttujia (lausekkeita) EtsiSuurin-lohkossa ja tulevat näkyviin kun ohjelman suoritus etenee sinne saakka.

Watch4
Watch4

Nyt watch-ikkunasta on helppo tarkastella esimerkiksi taulukon arvoja sitä mukaa kun silmukka etenee. Juuri muuttuneet arvot merkitään punaisella, aivan kuten Locals-paneelissa.

Watch5
Watch5
# valuechange

3.9 Muuttujan arvon muuttaminen

Tarvittaessa muuttujan arvoa voi muuttaa esim Locals-ikkunassa klikkaamalla arvoa ja sitten antamalla sille uuden arvon.

# ehdollinen

3.10 Ehdollinen keskeytyskohta

Debuggerin avulla voidaan lisätä myös ehdollinen keskeytyskohta eli Breakpoint Condition (joissain muissa IDEissä myös conditional breakpoint). Sen avulla debuggeri keskeyttää ohjelman suorittamisen breakpointin kohdalle heti kun breakpointille annettu ehto toteutuu. Ehto voi olla esimerkiksi muuttujan tietty arvo.

Tämä on hyödyllistä etenkin ohjelmassa jossa on esimerkiksi pitkä silmukka, joka halutaan pysäyttää jossain tietyssä kohdassa. Jos ohjelma pysähtyisi jokaisella kierroksella, olisi hyvin työlästä ajaa ohjelmaa haluttuun pisteeseen. Ehdon voi lisätä seuraavasti:

  1. Siirry haluamallesi riville koodissa

  2. Siirry rivin vasemman marginaalin harmaaseen alueeseen ja klikkaa siihen breakpoint (näkyy punaisena täplänä)

  3. Paina breakpointin kohdalla hiiren oikeaa näppäintä saadaksesi esiin valikon

  4. Valitse valikosta Condition, ilmestyy ikkuna Breakpoint Condition

  5. Tekstikenttään pitää lisätä lauseke, joka saa ajon aikana arvon true tai false, esimerkiksi

    luku == 4

    Sen sijaan

    int luku = 4 

    ei ole ehto, eikä kenttään voi myöskään laittaa if-sanaa. Kun lauseke saa arvon true debuggeri keskeyttää ohjelman suorittamisen. Muutamia muita esimerkkejä ehdoista:

    i > 3
    luvut[i+2] != 3
    pallot[i] == null
  6. Debuggaa (F5)

  7. Kun pysähtyy, tarkastele Locals- ja Watch-ikkunoista muuttujien arvoja ja jatka tarvittaessa Step into (F11), Step over (F10) tai Continue (F5).

Macilla ehdollinen Breakpoint asetetaan “New Breakpoint” komennolla kun avaa hiiren oikealla. https://docs.microsoft.com/en-us/visualstudio/mac/debugging?view=vsmac-2019

23 Oct 20

3.11 Hit Count

Hit Countilla voit laittaa ehdon niin, että kun näin monennen kerran tullaan keskeytyskohtaan, niin silloin pysähdytään.

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.