Debuggaus
Tässä esitellään lyhyesti debuggauksen tarkoitus ja Riderin tärkeimmät debuggaustoiminnot. Vaikka jokaisessa kehitysympäristössä on omat debuggaustapansa, ovat periaatteet hyvin pitkälti yhteisiä eri ympäristöjen välillä.
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.
Muita Rider-ohjeita:
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 Riderissa
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.
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
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.
Riderissa vie hiiri ikkunan vasempaan reunaan rivinumeroiden ja koodin väliin. Jos käytät New UI -käyttöliittymää, klikkaa rivinumeron kohdalle.
Keskeytyskohtaa EI voi asettaa Riderissä tyhjille riveille, kommenttiriveille eikä esittelyriveille. Toisin sanoen keskeytyskohdan voi asettaa vain suoritettaville riveille.
Paina hiirellä keskeytyskohta haluamaasi kohtaan.
3.2 Debuggaustilan käynnistäminen
Ohjelma käynnistyy debuggaustilaan painamalla joko F5, klikkaamalla oikean ylälaidassa olevaa Debug painiketta tai valitsemalla valikosta Run -> Debug. Tällöin ohjelman suoritus "pysähtyy" ensimmäiseen asettamaasi keskeytyskohtaan.
Huomaa, että keskeytyskohdan osoittaman punaisen pallon vieressä 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 keskeytyskohta on asetettu. Korostan: tätä keltaisen nuolen osoittamaa asiaa ei ole vielä suoritettu.
On mahdollista suorittaa ohjelma myös ilman debuggausta (Ctrl + F5 tai valitsemalla Run). Tällöin keskeytyskohdat jätetään huomiotta. Toisaalta myös esimerkiksi poikkeuksia (exceptions) ei käsitellä Riderin avulla, vaan ohjelmat voivat kaatua hallitsemattomasti.
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
Step over -toimintoa kannattaa käyttää sellaisen aliohjelmakutsun kohdalla, jonka sisäistä logiikka ei ole tarkoitus tarkastella. Esimerkiksi Console.WriteLine
- aliohjelmakutsun kohdalla kannattaa mieluummin valita Step over kuin Step into, sillä meitä ei oikeastaan kiinnosta tuon aliohjelman toiminta.
3.4 Resume
Resume-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 Run -> Stop debugging.
3.6 Muuttuja-arvot (locals)
Debuggaus‐näkymän Threads & Variables-paneelissa (tai välilehdellä) näkyy tällä hetkellä näkyvissä olevat muuttujat ja niiden arvot.
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. Riderissa muuttujan arvoa voi locals-ikkunassa muokata painamalla F2 tai klikkaamalla hiiren oikealla ja valistemalla Set Value.
Huomautus double-tyyppisen arvon muuttamisesta: Double-tyyppisen muuttujan arvoa muutettaessa on arvoksi asetettava desimaaliluku, esimerkiksi 3.0. Mikäli asetat arvoksi kokonaisluvun, esimerkiksi 3, debuggeri antaa virheilmoituksen "Error: Size of source and of dest differ".
JetBrains Rider: muuttujan arvoa voi muokata locals-ikkunassa painamalla F2 tai oikeaklikkaamalla ja valitsemalla Set Value. -JuhoK
—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.
Jos kutsupinoa ei näy Debug-näkymässä, saa sen esille valitsemalla klikkaamalla paneelin oikeassa yläreunassa olevaa ikkunan näköistä kuvaketta: Layout settings -> Threads Frames -> Side by side.
Riderin kutsupinossa ei valitettavasti näy lähdekoodin rivinumeroita siitä, miltä riviltä kutsuun on lähdetty. Mutta klikkaamalla kutsupinossa hiiren oikealla, voidaan ottaa pinon sisältä leikepöydälle ja sitten tarkastella sitä rivinumeroineen jossakin editorissa.
3.8 Watch
Paikallisten muuttujien lisäksi voidaan suorituksen aikana seurata itse valittuja muuttujia Add to Watches toiminnolla. Yksittäisten muuttujien lisäksi voidaan tarkastella lausekkeita, esimerkiksi taulukko[i] > suurin
(tuottaisi true
tai false
).
- Aseta keskeytyskohta haluamaasi paikkaan ja aloita debuggaus.
- Etsi koodista se muuttuja (tai lauseke), jonka tilaa haluat tarkkailla ajon aikana. Valitse se (maalaamalla esimerkiksi hiirellä), klikkaa sitten hiiren oikealla ja valitse Add to Watches. Alla olevassa kuvassa lisätään
suurin
-muuttuja locals/watch-paneeliin.
- Voit lisätä eri "watcheja" haluamasi määrän. Alla lisätään myös
i
,taulukko[i]
jataulukko[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ä 10.
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.
Nyt watch-ikkunasta on helppo tarkastella esimerkiksi taulukon arvoja sitä mukaa kun silmukka etenee.
3.9 Muuttujan arvon muuttaminen
Tarvittaessa muuttujan arvoa voi muuttaa esim Locals-ikkunassa klikkaamalla arvoa ja sitten antamalla sille uuden arvon.
3.10 Ehdollinen keskeytyskohta
Debuggerin avulla voidaan lisätä myös keskeytyskohdalle keskeytymisen ehto. Tällaista keskeytyskohtaa kutsutaan nimellä ehdollinen keskeytyskohta. Sen avulla debuggeri keskeyttää ohjelman suorittamisen vain, kun keskeytyskohtaan annettu ehto toteutuu. Ehto voi olla mikä tahansa totuusarvoinen lauseke, 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:
Siirry haluamallesi riville koodissa
Siirry rivinumeron koodiin väliin ja klikkaa siihen breakpoint (näkyy punaisena täplänä)
Paina breakpointin kohdalla hiiren oikeaa näppäintä saadaksesi esiin valikon
Lisää Condition tekstikenttään 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
Debuggaa (F5)
Kun pysähtyy, tarkastele Locals- ja Watch-ikkunoista muuttujien arvoja ja jatka tarvittaessa Step into (F11), Step over (F10) tai Resume (F5).
Macilla ehdollinen Breakpoint asetetaan “New Breakpoint” komennolla kun avaa hiiren oikealla. https://docs.microsoft.com/en-us/visualstudio/mac/debugging?view=vsmac-2019
—3.11 Hit Count
Hit Countilla voit laittaa ehdon niin, että kun näin monennen kerran tullaan keskeytyskohtaan, niin silloin pysähdytään.
4. Ongelmia debuggaustilan käynnistymisessä?
4.1 class com.intellij.util.ui.components cannot be cast
Mikäli saat debuggauksen aikana Riderissa poikkeuksen, esim.
class com.intellij.util.ui.components.BorderLayoutPanel
cannot be cast to class com.intellij.ui.OnePixelSplitter
kokeile asetusten resetointia seuraavien ohjeiden mukaisesti
HUOM! Näin tekemällä menetät kaikki asetuksesi, kuten näppäinoikotiet sekä teemat. Ota asetuksistasi halutessasi varmuuskopiot File -> Manage IDE Settings -> Export Settings.
- Paina Shift+Shift (eli kaksi kertaa Shift-painiketta) tai Ctrl+T,
- kirjoita Restore Default settings ja valitse ko. toiminto
- Rider käynnistyy uudestaan, valitse haluamasi asetukset.
4.2 Rider clr load callback is already in error state. A debug component is not installed
Jos saat yllä mainitun virheilmoituksen kun yrität käynnistää debuggerin niin ongelmana on todennäköisesti, että Mac-koneelle on asennettu väärä versio Riderista.
Joudut siis asentamaan Riderin uudestaan:
- Mene sivulle: https://www.jetbrains.com/rider/
- Klikkaa Download
- Valitse omalle koneellesi sopiva versio ja lataa se
- Asenna Rider uudelleen
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.