Johdanto ja tavoite
Tässä osiossa tutustutaan Visual Basic:in debuggausmahdollisuuksiin ja opitaan tuntemaan erilaisia
virhetyyppejä. Tämän osion jälkeen opiskelija osaa käyttää Visual Basic:n debuggausominaisuuksia
tehokkaasti ja erottaa erityyppiset ohjelmakoodivirheet.
Virhe
Virheitä on monenlaisia ja ohjelmakoodivirheistä puhuttaessa ne voidaan jakaa kolmeen eri tyyppiin.
Selkeäsi helpoiten havaittava virhe on syntaksivirhe, jonka VB huomaa viimeistään ohjelmakoodia
ajettaessa tai käännettäessä. Tämä tarkoittaa esim. sitä, että yrität kirjoittaa MsgBox:n sijasta
msbox:n, tällaista käskyä ei ole ja VB kertoo siitä pyytäen korjaamaan virheen.
Toinen virhetyyppi on ajonaikaiset virheet. Tällainen virhe syntyy, kun ohjelmakoodi on syntaktisesti
oikein mutta se yrittää tehdä asiaa, joka on mahdotonta. Yksi tällainen asia on nollalla jakaminen
joka synnyttää virheen.
Viimeinen virhetyyppi on looginen virhe. Tällöin ohjelma toimii, ei kaadu ajonaikaiseen virheeseen
mutta tulos on väärä.
Syntaksivirhe
Syntaksivirheitä ei käsitellä sen enempää, VB huomaa ne kyllä ja pyytää sinua korjaamaan ne.
Ajettaessa ohjelmaa VB:ssä voit varmistaa ohjelmakoodin syntaksin oikeellisuuden ajamalla ohjelma
Run (F5 -painike) -komennon sijasta Start with Full Compile (CTRL - F5 -painikkeet) -komennolla
joka kääntää ohjelmakoodin ennen sen suoritusta varmistaen, ettei siinä ole syntaksivirheitä.
Muutoin ohjelmaa ajettaessa ohjelmakoodin suoritus voi keskeytyä syntaksivirheeseen. Toki virheen
voi tietyissä tapauksissa "korjata lennossa" mutta huonolla tuurilla em. korjaus voi kaataa VB:n.
Esimerkissämme virhe syntyy kun yritämme kutsua MsgBox -käskyn sijasta msbox -käskyä jota ei ole
olemassa.
Syntaksivirhe.
Ajonaikaiset virheet
Ajonaikaisia virheitä on aina, näitä kutsutaan joskus myös bugeiksi. Ohjelmoija ei voi aina ennustaa
mitä tapahtuu, hyvä esimerkki on tiedoston tallennus. Entäpä jos korppu on täynnä? Tai koko korppua
ei ole asemassa? Tästä voi syntyä ajonaikainen virhe joka voidaan toki käsitellä käyttämällä ns.
virheenkäsittelyä. Esimerkissämme ajonaikainen virhe syntyy, kun
yritämme jakaa luvun 50 luvulla 0.
Ajonaikainen virhe.
Looginen virhe
Kaikista pahin virhe on looginen virhe. Ohjelma toimii näennäisesti oikein, ei kaadu virheisiin
mutta lopputulos on puutaheinää. Tällainen voi syntyä huolimattomasta ohjelmakoodin kirjoittamisesta.
Esimerkissämme looginen virhe syntyy, kun laskemme (ihan oikein) lausekkeen luku 50 jaettuna luvulla 5
tuloksen olla 10. Tallennamme tuloksen oikein muuttujaan Z mutta tulostammekin muuttujan a jota
ei ole käytetty ja joka on tyhjä. Tämäkin virhe olisi vältetty, jos meillä olisi käytössä Option Explicit
-lause, joka vaatii alustamaan kaikki käytettävät muuttujat.
Looginen virhe.
Debuggaus
Joskus (etenkin ajonaikaisen virheen syntyessä tai ohjelman toimiessa eri tavalla kuten pitäisi) on
hyvä pystyä keskeyttämään ohjelmakoodin suoritus ja seurata suoritusta rivi riviltä tai esim. funktio
funktiolta.
Ohjelman keskeyttäminen
Voit keskeyttää ohjelman suorituksen parilla eri tavalla. Yksi tapa on lisätä ohjelmakoodiriville harmaalle
alueelle punainen täplä, ns.
keskeytyskohta johon tultaessa ohjelmakoodin suoritus
keskeytetään automaattisesti. Toinen tapa on painaa CTRL-BREAK -näppäintä. Tämä on tarpeen silloin, kun
haluat pysäyttää ohjelmakoodin suorituksen spontaanisti, esim. jos ajaudut ikuiseen silmukkaan.
Kuvassa olemme määrittäneet keskeytyskohdaksi haluamme rivin suoraan ohjelmakoodiin.
Kuvassa olemme keskeyttäneet ohjelman suorituksen painamalla CTRL ja BREAK -näppäimiä.
Ohjelmakoodin suorittaminen
Kun olemme saaneet ohjelmakoodimme pysäytettyä, on hyvä alkaa tutkimaan mikä siinä mahdollisesti on
vikana (tai ihan muuten vain tutkailla ohjelman suoritusta). Voit suorittaa ohjelmakoodirivin
napsauttamalla F8 -näppäintä tai valitsemalla Debug -valikosta Step Into -toiminnon. Muista, että näet
nykyisen (ei vielä suoritetun) ohjelmakoodirivisi keltaisen vilkkuvan nuolen kohdalla. Jos ohjelmakoodirivillä
on esim. funktiokutsu ja haluat seurata ohjelman suoritusta em. funktioon, napsauta F8 -näppäintä.
Jos taasen haluat, että em. funktio suoritetaan mutta et halua seurata sen suoritusta, napsauta CTRL- ja
F8 -näppäimiä jolloin VB suorittaa em. rivin (ja funktion) ja kohdistus palaa seuraavalle koodiriville.
Huom! Muuttujamäärittelyihin ja vastaaviin määrittelykohtiin ei voi "pysähtyä" rivi kerrallaan toiminnolla.
Tarkemmat tiedot debuggausvalikon toiminnoista löydät täältä.
Välitön ikkuna
Ohjelman ollessa keskeytettynä on hyvä tutkia muuttujien arvoja. Yksi tapa on laittaa hiiren kursori
muuttujan päälle, arvo ilmaantuu
pikaohjeeseen.
Pikaohje.
Toinen tapa nähdä muuttujien arvo on tulostaa ne Immediate -ikkunassa. Jos em. ikkuna ei näy, saat
sen esiin View -valikon Immediate Window -toiminnolla. Tähän ikkunaan voit kirjoittaa ohjelmakoodia
joka suoritetaan kun painat Enter:iä. Voit tulostaa esim. muuttujien arvoja kirjoittamalla print
-komennon (tai pelkästään ?) ja muuttujan nimen:
Muuttujan arvon tulostus.
Kuvassa on esitetty kuinka muuttujan arvo voidaan tulostaa kirjoittamalla Print (tai ?) ja muuttujan nimi.
Ohjelmakoodin suorittaminen.
Toisessa esimerkissä asetamme muuttujan X arvoksi 5 ja tulostamme muuttujan arvon MsgBox -käskyä käyttäen.
Instant Watch
Toinen tapa tutkailla muuttujan arvoja on ns. Watch:n käyttäminen. Tällöin määrittelemme "seurattavat"
muuttujat. Nopea tapa lisätä muuttuja seurattavien muuttujien listaan on pysäyttää ohjelmakoodin suoritus,
laittaa hiiren kursori sen muuttujan päälle jota haluaa seurattavan, napsauttaa oikeaa painiketta
ja valita aukeavasta valikosta Add Watch -toiminto.
Instant Watch:n aktivoiminen.
Avautuvasta ikkunasta voi määritellä haluttu lauseke joka muuttujaan kohdistuu,
missä aliohjelmassa, moduuleissa ja projektissa muuttujaa seurataan ja katkaistaanko ohjelman suoritus
kun lauseke toteutuu vai näytetäänkö vain muuttujan arvo.
Watch:in määrittely.
Napsauttamalla OK -painiketta muuttujaa seurataan vain nykyisessä aliohjelmassa nykyisessä lomakkeessa
nykyisessä projektissa ja näytetään pelkästään muuttujan arvo.
Kuvassa seuraamme muuttujan arvon muuttumista ohjelman suorituksen aikana.
Jos haluat, voit lisätä Watch:iin myös monimutkaisempiakin lausekkeita. Lisäämme nyt lausekkeen, joka
pysäyttää ohjelman suorituksen kun muuttuja X saa arvon 5. Määrittelemme lausekkeeksi siis: X=5.
Context -kehyksen asetukset kelpaavat suoraan, meille riittää oletusasetukset. Watch Type -kehyksessä
on kolme vaihtoehtoa: Watch Expression joka vain näyttää muuttujan arvon, Break When Value
Is True joka keskeyttää ohjelman suorituksen kun em. lauseke on tosi (eli X:n arvo on 5) ja Break
When Value Changes joka pysäyttää ohjelman suorituksen aina kun valitun muuttujan (tässä tapauksessa
tietysti muuttujan X) arvo muuttuu.
Määrittelemme Instant Watch:in lausekkeeen.
Kun suoritamme ohjelmakoodia, suoritus pysähtyy automaattisesti kun muuttuja X saa arvon viisi
tässä metodissa tässä lomakkeessa ja tässä projektissa.
Debug
Voit halutessasi käyttää ohjelmakoodissa ns. väliarvojen tulostamiseen Debug -oliota. Debug -oliolla
on kaksi metodia,
Print ja
Assert. Käyttämällä Print -metodia tulostat ns. Immediate Window:iin.
Alla olevassa esimerkissä tulostamme muuttujan X arvon käyttämällä Debug -olion Print -metodia:
Debug -olion Print -metodin käyttäminen.
Assert -metodilla ohjelmakoodin suoritus pysähtyy jos ehto on epätosi.
Jos ehto on tosi, Assert -lause "ohitetaan". Assert -lause toimii vain VB:ssä, kun ohjelmakoodi
käännetään EXE:ksi, Assert -lauseita ei oteta mukaan.
Virheen korjaaminen
Käytimme em. debuggausmahdollisuuksia ja löysimme ohjelmakoodistamme ainakin kaksi virhettä. Ensimmäinen
virhe liittyy Do Loop While -silmukan ehtoon, jossa määritellään, että silmukassa pysytään niin kauan
kun muuttujan X arvo on pienempi kuin 10 (X < 10). Ongelmana tässä on se, että muuttujan X arvo on
aloitettaessa 10 joten suoritettuamme yhden kierroksen ohjelmakoodimme hyppää silmukasta pois.
Korjaamme siis virheen, muutamme silmukan ehdoksi seuraavan: X < 10. Nyt huomaamme pian toisen
ongelman, muuttujan X arvo ei muutu joten olemme ns. ikuisessa silmukassa!
Korjaamme taas ongelman, lisäämme lausekkeen, joka vähentää muuttujan X arvoa yhdellä jokaisella kierroksella.
Nyt ohjelmakoodimme on toimiva!
Dim X As Long
X = 10
Do
MsgBox "Kierros " & X
X = X - 1
Loop While (X > 0)
Yllä on esitelty
korjattu ohjelmakoodi.