Debuggolás IDE-vel¶
A debuggolás olyan folyamat, amely segít megtalálni a program hibáit. Az IDE-kben található debugger (GDB vagy saját készítésű). Ahhoz, hogy használhassuk, fordítsuk/indítsuk a projektet Debug módban, így a debuggolást segítő extra szimbólumok kerülnek a binárisba. A printf
alapú debuggolást bizonyára mindenki használta már.
A Debug mód használata ezt a fajta debuggolást teszi gyorsabbá és konfigurálhatóbbá. A Debug módban futó kódhoz kapunk egy ilyesmi kezelőfelületet:
Fukciók balról jobbra:
- Continue: A Debug módú futás újraindítása, mikor breakpointnál áll a program
- Stop: Futás leállítása
- Pause: debugger futásának felfüggesztése (nem breakpointnál, hanem ahol éppen áll)
- Restart: teljesen újraindítja a Debug módú futtatást
- Show current line: odaugrik a sorra, ahol épp a végrehajtás áll
- Step into: Következő utasítás végrehajtása úgy, hogy az esetleges függvényhívásokba is belelépünk
- Next: Következő utasításra lépünk, de a függvényhívásokba nem lépünk bele
- Step out: Befejeződik az aktuális metódus végrehajtása és a hívási ponton fog megint felfüggesztődni a program futása.
A képek CodeLite segítségével készültek. Minden IDE debugger felülete hasonló elveken alapszik.
Breakpoint¶
A legtöbb IDE-vel a kódsorok elé kattintva breakpointokat helyezhetünk el. Jelük általában egy piros pötty. Ha Debug módban indítottuk el a programot, akkor a megjelölt sorban lévő utasítás végrehajtása előtt fel lesz függesztve a program futása. Ilyenkor hasznos információkhoz juthatunk, például megnézhetjük a lokális változókat, azok adattagjait stb.
Feltételes breakpoint¶
Ha azt szeretnénk, hogy a breakpointnál csak bizonyos esetekben álljon meg a program futása, feltételeket is megfogalmazhatunk. Jobb egérgombbal kattintva a breakpointokra részletesen szerkeszthető.
A képen a feltételt alulról a második szövegmezőben szerepel: i == 2
, vagyis csak akkor fog megállni itt a debugger, ha a lokális i
változó értéke 2 (igazra értékelődik ki a feltétel). Az alsó szövegmezőbe utasításokat lehet megadni, amik megálláskor hajtódnak végre. Például:
1 2 |
|
Kiíratja az i
változó értékét, utána a continue
paranccsal folytatódik a program végrehajtása. CodeLite esetén itt a gdb-ben adunk parancsokat. A gdb-ről és a lehetséges parancsokról a következő anyagban lesz szó.
Lépkedés az utasítások között¶
A végrehajtás az alsó képen látható breakpointnál áll. Ekkor a my_to_upper
még nem hívódott meg.
A Step in megnyomására belépünk a my_to_upper
-be.
Ha megint Step in-t nyomunk, akkor a függvény utasításain kezdünk el lépkedni (mivel nincs függvényhívás egyik utasításba sem, ezért nem ugrik bele semmibe. Ebben az esetben ugyanaz a hatása, mintha Next-et nyomnánk.
Ha nem akarunk végigmenni a my_to_upper
összes utasításán, a Step out-al gyorsan előreugorhatunk a hívás helyére. Vagyis befejeződik a my_to_upper
futása és a végrehajtás a hívási helyen, azaz a main
-ben fog állni. Következőleg a hívás utáni első utasítást fogja végrehajtani. Itt vagy újraindítjuk a program futását (continue
) vagy lépkedünk tovább egyesével
Hasznos információk kinyerése¶
Az utasításonkénti végrehajtás során hasznos adatokat olvashatunk ki a programról. Megnézhetjük például a lokális változók értékeit, a hívási láncot, a végrehajtási szálakat, kiírathatjuk konkrét memóriaterületek tartalmát stb.
Lokális változók¶
A képen a fentebbi my_to_upper
függvény lokális változóit láthatjuk. Megmondja nekünk a debugger, hogy a paraméterben kapott inp
pointer, egy olyan memóriaterületre mutat, ami a halt and CATCH fire
stringet tartalmazza. Ha szükséges, jobb egérgombbal felül tudjuk írni a változók értékeit.
Call stack¶
Ha valahol megáll a debugger, akkor az aktuális stack frame lokális változói mellett a call stack-et is nézegethetjük, vagyis a hívási láncot, ami az adott állapothoz elvezetett. Ez nagyon hasznos lehet olyankor is, amikor a programunk kap egy segmentation fault-ot vagy kivétel dobódik.
A képen a hívási lánc csak két elemű: a main
-ből meg lett hívva a my_to_upper
függvény. A táblázat legszélén látjuk a konkrét utasítások memóriacímét is, ahol a végrehajtás áll illetve ahonnan a rákövetkező függvény hívása megtörtént.
Watch¶
A watch (figyelő) feltételek egy változó vagy egy kifejezés aktuális értékének változását monitorozzák. Olyasmi, mint egy feltételes breakpoint, annyi különbséggel, hogy a watch az érték változása esetén állítja meg a futást (a feltételes breakpoint pedig akkor, ha az adott utasításra lépve teljesül a feltétel). A watch-t akkor tudjk beállítani, ha a program épp fel van függesztve és a hivatkozott változók scope-on belül vannak.