Siluri kasutamine Geanys

Silur ehk debugger on tööriist, millega saab koodi jooksutada rida-rea haaval ning analüüsida programmi, sh selle muutujate väärtusi, funktsioonide pinu (function call stack) jpm.

Sellist liiki töövahendid on tarkvara arenduses igapäevased ning nende kasutama õppimine lihtsustab oluliselt tarkvara loomist. Enamik koodiredaktoreid tuleb kas siluritega juba kohe kaasa pakendatult (nt CLion, Visual Studio jt) või saab neid juurde lisada (nt Geany, Visual Studio Code). Sageli on silurid lihtsalt eraldi programmid (nt GDB ehk GNU Debugger), millele pakutakse lihtsalt liidest koodiredaktori sisse.

Geany puhul lisame me pistikprogrammi (plugin), mis annab meile visuaalse kasutajaliidese kasutamaks käsurea põhist silurit GDB.

Seadistamine

Enne siluri kasutusele võttu tuleb teha paar ühekordset liigutust selle seadistamiseks. Seadistuse on vajalik sinu enda arvutis. Kooliarvutites on seadistus juba tehtud.

Siluri pistikprogrammi paigaldus

Kui jälgisid meie poolt pakutud Geany paigaldusjuhendit on sul juba kõik tehtud ja võid selle osa vahele jätta. Mine järgmise peatüki juurde (siluri aktiveerimine)!

Kui ei, siis paigalda endale pakett nimega geany-plugin-debugger.  Kasutades ükskõik millist Ubuntu põhist Linuxit tuleks selleks käivitada järgnev käsk:

Paketi võid paigaldada eraldi või siis koost teiste Geany pistikprogrammidega pakist geany-plugins .

Siluri pistikprogrammi aktiveerimine

Märkus: Kooliarvutis on silur juba aktiveeritud.

Aktiveerimaks silurit mine Geany sees menüüsse Tools -> Plugins.

Otsi üles Debugger ning pane sellele linnuke ette

Kompilaatori seadistamine

Märkus: Kooliarvutis on kompilaator juba seadistatud.

Selleks, et silur saaks töötada ning su programmist aru tuleb meil kompilaatorile anda täiendav käsk -g .  Antud käsuga lisatakse su programmi kompileeritud versioonile kaasa silumiseks vajaminev lisainformatsioon. Selle tulemusena läheb programm oluliselt suuremaks ja aeglasemaks, kuid ühtlasi võimaldab see meil ka silureid ja erinevaid tarkvara analüüsi rakendusi kasutada. Ära unusta see lipp välja lülitada kui peaksid kliendile tarkvara üle andma!

Märkus: järgnevat saab teha ka valides menüüst Build -> Set build commands, kuid siis peab olema .c koodifail parasjagu redaktoris avatud. Juhend on koostatud sedasi, et seda pole vaja teha.

Avame C koodifailidega seotud Geany konfiguratsioonifaili Tools -> Configuration files -> Filetype Configuration -> Programming Languages -> filetypes.c

 

Avanenud konfiguratsioonifaili reale FT_01_FM tuleks lisada kompileerimise argument -g . Joonisel on see punasega alla joonitud. Veendu, et enne ja pärast lisatud argumenti oleksid tühikud. Antud argumenti ei tohi kirjutada -o  järele.

Näide minu konfiguratsioonifailist pärast lisamist (punane on lisatud argumendil).

Kopeeritaval kujul saad kõik selle järgnevast kastist. Märka, et mul on ka täiendavaid argumente kasutusel nagu -Wextra  ja -Wconversion  (soovi korral võid need eemaldada)

Siluri kiirklahvide seadistamine

Selle peatükiga sa ilmselt veel koheselt midagi tarka teha ei oska. Küll aga võid tahta siia tagasi tulla pärast seda kui oled juba mõne korra silurit kasutada proovinud.

Siluril pole vaikimisi kiirklahve seadistatud (ehk näiteks F5 käivitab jätkuvalt programmi normaalselt, mitte koos siluriga. Pärast seda kui oled aru saanud mida silur teeb ja kuidas tahad sa ilmselt mõne täiendava klahvikombinatsiooni endale sättida. Selleks vali Edit -> Preferences. Avanenud seadistuste aknast vali Keybindings ning keri alla kuniks jõuad Debugger alamjaotuseni. Siin saad endale klahvikombinatsioone luua siluri kasutamiseks.

Mõned huvipakkuvatest võiksid olla Run / Continue, Step into, Step over, Steo out, Run to cursor jne.

Siluri kasutajaliides

Pärast pistikprogrammi lubamist tekib alla täiendav aken nimega Debug. Avades selle kaardi kuvatakse järgnev vaade

1 – Kasti Target tuleb määrata programm, mida soovid siluda. Seda on vaja iga kord uuendada kui soovid mõnda teist koodifaili siluda. Selle all paiknevad programmile antavad käsurea argumendid.

2 – Siin on programmi jooksutamise kontrollmehhanismid – käivitamine, peatamine, samm-haaval läbimine jne.

3 – Siin paikenvad erinevad vaated kus saab nähta infot jooksva programmi kohta

  • Target kirjeldab ära jooksutatava programmi ja selle keskkonnamuutujad ning käsurea argumendid
  • Breakpoints näitab ära read mille peal kood seisma jääb
  • Autos näitab automaatselt hetkel skoobis olevate muutujate väärtusi (nt funktsioonis olles näitab funktsiooni lokaalmuutujaid).
  • Watch alla saad lisada muutujaid topeltklõpsuga Autos olevale muutuja nimele või kirjutades nime või valemi täpselt sisse.
  • Call stack näitab funktsioonide pinu ehk siis alates mainist mis funktsiooni sees oled. Samuti näeb mitmelõimuliste (multithreaded) programmide puhul teisi lõime (thread)
  • Debug Terminal näitab tavapärast terminaliakent. Sinna saab ka teksti kirjutada.
  • Debugger Messages näitab GDB väljundit.

4 – See on üks oluline nupuke, millega saab all oleva vaate kaheks tükis teha. See on tähtis kuna nii on mugavam üheaegselt jälgida muutujate väärtusi ja näha programmi väljundit, vastasel juhul asuvad need erinevatel kaartidel ja nende vahel tuleb programmi töö jooksul klõpsida edasi-tagasi.

Alternatiivne UI kui see on kaheks jagatud näeb välja järgnev

Programmi silumine

Siluri kasutamiseks tuleks esmalt selgeks teha kus kohas midagi asub ehk tutvuda kasutajaliidesega.

Näidises kasutatud koodilõigu leiad siit: https://blue.pri.ee/ttu/files/iax0584/demokood/demo_debugger.c

1. Vali silutav programm

Esimene samm iga programmi silumisel on silurile jooksutatava programmi asukoha seadistamine. Silur ei ürita automaatselt seda koodifaili siluda mis sul lahti on! Tavapäraselt võib üks programm koosneda sadadest koodifailidest, millest vaid ühes asub main funktsioon – seetõttu tuleb silurile ette näidata kus asub silutav programm.

Mine paanile Target ja kliki ikoonil Browse. Seejärel otsi üles oma programm mida soovid siluda. Programmi asukoht peab ilmuma selle kõrval olevasse tekstikasti (.c failid ei ole programmid!)

Siia saad lisada ka programmile vajaminevaid käsurea argumente ja keskkonnamuutujaid.

2. Määra katkepunkt või katkepunktid

Teisena tuleb meil määrata katkepunkt (breakpoint), kus soovime, et programm jääks automaatselt seisma. Selliseid punkte võime lisada rohkem kui ühe ning kui programm on üle mitme faili, siis neid saab lisada erinevatesse failidesse. Pärast käivitamist jookseb programm senikaua kuniks kohtab esimest meie poolt märgitud katkepunkti ning seejärel läheb üle silumisrežiimi.

Katkepunkti määramiseks klõpsa rea numbri järel olevale tühjale alale. Sinna tekkinud punane täpp tähistab katkepunkti. Näiteks antud programmi on lisatud reale 34 katkepunkt.

Katkepunkte saab lisada ka kiirklahvidega.

3. Käivita programm siluris

Programmi töö kontrollimiseks on siluri akna paremal küljel. Vajuta sealt Run nuppu. Peatamiseks vajuta Stop nuppu.

Pärast käivitumist jookseb silur kas esimese katkepunktini või sinnamaani kus ta peab kasutajalt sisestust küsima. Olles kahepaanilises vaates on sul vasakul pool peamiselt programmi info, paremal pool terminalid ja funktsioonide informatsioon.

Hetkel peatus programm kasutaja sisestuse juures. Meie poolt pandud katkepunktini ei ole veel jõutud! Sinna jõutakse pärast scanf  täitmist, seega peame terminali andma sisendi.

Olles numbri ära kirjutanud jääb meie programm uuesti seisma. Seda seetõttu, et nüüd jõudsime oma katkepunktini. Kui vaatad vasakus paanis Autos kaarti näed, et sinna on automaatselt tekkinud funktsiooni lokaalmuutujad. Paremal pool on aga avanenud sulle juhtimiseks kaustatavad kontrollnupud.

4. Samm-sammuline läbikäik

Olles jõudnud katkepunktini saad programmi juhtida samm-sammu haaval. Selleks on kõrval nupud:

  • Continue – programm jätkab tavarežiimis kuniks kohtab uuesti katkepunkti. Vajadusel peatutakse kasutajalt sisestuse küsimiseks, kuid silumisrežiim aktiveerub vaid siis, kui satud järgmisse katkepunkti.
  • Restart – käivitab programmi uuesti
  • Stop – peatab programmi
  • Step over – Astub funktsioonist üle (funktsiooni sisu täidetakse, kuid silur ise sinna sisse samm-sammu haaval käske täitma ei lähe)
  • Step into – Astub funktsiooni sisse mida parasjagu kutsud – saad kutsutava funktsiooni sisu samuti samm-sammu haaval läbi käia. NB! Ära kasuta standardteekides olevate funktsioonide jaoks (nt printf, scanf, …)
  • Step out – astub praegusest funktsioonist välja ja jätkab silumist eelnevast funktsioonist kust praegune välja kutsuti
  • Run to cursor – Saad koodiaknast liigutada kursori uude asukohta, kus tahad, et programm seisma jääks. Kuni sinnamaani läheb programm tavarežiimi tagasi. Tegu on sisuliselt automaatse katkepunktiga. NB! Kui programm kohtab enne kursori asukohta mõnda teist katkepunkti, siis jääb ta ka seal seisma.

Hoiatus! Ekraanile trükkimine on puhverdatud operatsioon. St iga printf  peale automaatselt nähtavat väljundit ei teki! Reeglina kuvatakse väljund ekraanile rea kaupa – st jõudes rea lõpusümbolini kuvatakse kogu rida korraga.

Koodist otse väärtuste vaatamine

Kui programm on silumisrežiimis saame me koodiaknas minna ükskõik millise muutuja või funktsiooni kohale hiirega mis asub meie skoobis. Sellisel juhul näidatakse kohe keset koodiakent selle muutuja või funktsiooni andmed.

Watch ehk vaatenimekiri

Selleks, et jälgida kindlaid muutujaid pidevalt saab luua vaatenimekirja Watch kaardi alla. Sinna saab lisada asju kahte moodi

  1. Jooksvalt programmi läbides kui soovitav muutuja on nähtav saad Autos kaardi all teha selle rea peal topeltklõpsu
  2. Olles Watch kaardil saad pärast viimast olemasolevat rida kirjutada name kohta soovitava kirje.

Antud näites on näidisprogramm peatatud pärast andmete sisse lugemist main() funktsioonis. On näha, et ReadValue funktsiooni parameetrid min ja max ei ole loetavad – me saame näha vaid parasjagu skoobis olevaid väärtusi. Küll aga saame me siia lisada oluliselt rohkem andmepunkte kui Autos seda võimaldas.

Näites on lisatud:

  • Kogu massiiv oma liikmetega
  • Üksik massiivi liige
  • Üksiku massiivi liikme mäluaadress (näitab ka millele viitab)
  • Matemaatilised operatsioonid olemasolevate väärtustega

Alamfunktsiooni edastatud massiivi sisu nägemiseks võimalik see käsitsi lisada watch nimekirja  järgmiselt: *massiiviNimi@pikkus

NB! Makrote väärtust pole võimalik lisada, sest meeldetuletus – kompileerimise käigus need likvideeritakse ja asendatakse konstantidega.

Käsureaargumentide silumine

Käsureaargumentide kasutamiseks silutaval programmil tuleb need määrata Target vahesakil, Command line arguments lahtrisse.

Programmi jooksutades kuvatakse Autos vahesakil kenasti argc  väärtus, kuid argumentide vektorist argv   kuvatakse automaatselt vaid esimene argument argv[0] . Parema ülevaate saamiseks lisame vaadeldava vektori käsitsi Watch vahekaardil, kasutades varasemalt tuttavat massiivi lisamise mustrit  arrayName@arrayLength .

Windows

Antud siluri versioon ei ole Windowsil kättesaadav. Sellegipoolest on Windowsi kasutajatel võimalik kasutada teist Geany pistikprogrammi silurile, mis on üpriski sarnane üleval kirjeldatule. Mõnes aspektis on see veidi mugavam, mõnes ebamugavam aga erinevused on pigem tühised.

Märkus: Allpool kirjeldatud silur on saadaval ka Linuxil, kuid ei ole kooliarvutites installeeritud.

Juhend siluri kasutamiseks Windowsis on üsna sarnane Linuxi versiooniga, seega toon välja vaid peamised erinevused.

Pistikprogrammi nimi on Scope Debugger

Silutava programmi ülesseadmine käib menüüribalt Debug -> Setup. Määra ära oma kompileeritud programmi asukoht lahtrisse Executable ja vajuta OK.

Tööriistaribale lisandusid uued nupud Katkestuse lisamiseks / eemaldamiseks klõpsa sinisel ringil. Ülejäänud nupud on mõeldud programmi töö kontrollimiseks ja samm-sammu haaval läbimiseks.