FAV-ZCU/KIV PPA1/9. Ověřování správnosti programu, ladění.md

9.7 KiB
Raw Permalink Blame History

Ověřování správnosti programu, ladění

  • Při vytváření programů je do zdrojového kódu (neúmyslně) zaneseno mnoho různých chyb od překlepů přes neošetření hraničních případů až po logické chyby v celkovém chování programu
  • Část chyb odhalí překladač (a upozorní nás na ně IDE nástroj) chyby při překladu
  • Část chyb překladač neodhalí a program jde přeložit
    • POZOR!
      • Pokud jde program přeložit, neznamená to, že funguje správně!
      • Program může (někdy nebo vždy) dávat nesprávné výsledky
      • Může docházet k chybám za běhu programu
  • Chyby, které překladač neodhalí (chyby za běhu programu), je třeba najít a opravit opakovaným opravováním, překládáním a spouštěním programu s využitím vhodných vstupních dat
    • Tato činnost se nazývá ladění (častěji debugging)
  • Lze provádět ručně nebo s využitím specializovaného nástroje zvaného debugger součást téměř všech IDE nástrojů
    • Často se používá kombinace obou přístupů
  • Vyšší fází ladění je testování
    • Zjišťuje se, zda program pracuje správně pro všechny typy vstupů, zda reaguje správně na neplatné vstupy apod.
    • Podrobně viz předmět KIV/OKS

Odhalení chyb při psaní zdrojového kódu a při překladu

  • Překladač javac umí odhalit především syntaktické chyby
    • Často způsobené překlepy v názvech proměnných, metod, zapomenutím na import třídy, zapomenutím deklarace proměnné, atd.
    • Všechny nalezené chyby jsou vypsány při překladu
  • Překlad v příkazové řádce
    • Pokud překládáme program ručně v příkazové řádce příkazem javac, objevíme chyby až po spuštění překladu
    • Protože překlad netrvá dlouho (pro malé programy), je možné provádět ho během vývoje opakovaně, např. při každém inkrementálním přidání funkcionality
      • Nalezené chyby lze průběžně odstraňovat
      • Odstranění chyby se ověří opakovaným překladem
    • Je možné i napsat celý program a poté odstranit chyby najednou
      • Odstranění chyb se opět ověří opakovaným překladem
    • POZOR!
      • Při opakovaném překladu se počty chyb mohou snižovat i zvyšovat
      • Překladač se snaží při překladu najít co možná nejvíce chyb tj. neskončí při první nalezené chybě, ale pokud to jde, pokračuje dále
      • Některé chyby jsou však z pohledu překladače natolik zásadní (ač z pohledu člověka vypadají banálně např. zapomenutý středník „;“ nebo složená závorka „}“), že mu znemožní kontrolu velké části kódu
      • Po opravení takové chyby může překladač tuto přeskočenou část zkontrolovat a tím odhalit další, dosud neodhalené chyby počet chyb může po odstranění chyby vzrůst

Čtení a porozumění výstupu překladače

  • Výstup překladače (tj. výpis chyb při překladu) se zobrazí po skončení překladu v příkazové řádce nebo v konzoli IDE nástroje
  • Výstup nemusí být stejný v IDE a v příkazové řádce

Ladění (debugging)

  • Pokud se program podaří přeložit, ještě to neznamená, že funguje správně
    • Většinou správně nefunguje, i když jde přeložit
  • Chyby v chování programu neodhalí překladač, musí je najít sám programátor
  • Chybné chování programu se typicky projevuje:
    • Program je předčasně ukončen s chybovým hlášením (vždy nebo někdy)
      • Je třeba rozumět chybovému hlášení
    • Program zdánlivě funguje, ale dává pro některé či všechny vstupy zcela špatné nebo částečně špatné výsledky
    • Ladění je možno provádět ručně tzv. metodou ladících výpisů a/nebo s využitím specializovaného ladícího nástroje (debuggeru)
    • POZOR!
      • Program se nedá považovat za odladěný po vyzkoušení jednoho či několika málo vstupů
      • Je potřeba zkoušet více různých vstupních hodnot, netypické hodnoty apod.
      • Je potřeba zkoušet i neplatné hodnoty, na něž by měl program adekvátně reagovat
        • To však zatím není probráno

Chybové hlášení za běhu programu

  • Pokud dojde za běhu programu k chybě (přesněji k vyhození výjimky) a tato chyba není v programu ošetřena, program je předčasně ukončen a do konzole (či příkazové řádky) se vypíše chybové hlášení
  • Chybové hlášení
    • Vypíše, o jakou chybu (výjimku) se jedná (její název a někdy i popis)
    • Vypíše tzv. stack trace (výpis zásobníku)
      • Zjednodušený obsah zásobníku (stack) programu v okamžiku, kdy k chybě došlo
      • Obsahuje volání metod je jasné, v jaké metodě přesně došlo k chybě (první uvedená metoda) a ze které metody byla tato metoda volána (další uvedená metoda)
      • Následují další metody, které byly hierarchicky volány až k metodě main()
      • V jednoduchých programech je většinou zobrazeno i číslo řádky, na které k chybě došlo
    • Hlášení o chybách za běhu programu typicky vypadají stejně v příkazové řádce i v konzoli IDE nástroje

Metoda ladících výpisů

  • Metoda ladících výpisů se používá, pokud nemáme k dispozici debugger, nebo ho z nějakého důvodu nechceme použít
  • Na vhodná místa programu vložíme volání metody System.out.println()
    • Můžeme vypisovat hodnoty důležitých proměnných
    • Můžeme pomocí výpisu unikátních značek (tj. textů) určit, kde se program
  • přesně nachází (podle toho, co a v jakém pořadí program vypíše)

Použití debuggeru v Eclipse

  • Debugger umožňuje dělat automaticky to, co musíme ručn pomocí kontrolních výpisů a umožňuje mnohem více
    • Sledování hodnot vybraných proměnných a výrazů
    • Krokování programu řádku po řádce
    • Nastavení breakpointů bodů, ve kterých se program zastaví a umožní od něj krokování
  • Spuštění debuggeru v Eclipse
    • Vytvoření breakpointu
      • Pro zapnutí debuggeru je potřeba nastavit breakpoint, tedy bod, od kterého bude program krokován
      • Breakpoint se na určitou řádku nastaví dvojklikem vlevo od požadované řádky
      • Alternativou je kliknout pravým tlačítkem na stejné místo => vybrat Toogle breakpoint
      • Přítomnost breakpointu na řádce je indikována symbolem
      • Stejným způsobem lze breakpoint odstranit
    • Spuštění debuggeru
      • Mít aktivní třídu s breakpointem
      • Debug as… => Java Application
      • Pokud si Eclipse není jistý, který program chcete debuggovat, dá vám na výběr
      • Pokud není zvolen žádný breakpoint, program proběhne jako při normálním spuštění
    • Po spuštění debuggeru program běží normálně, dokud nedosáhne breakpointu
      • Potom se objeví dotaz, zda chceme spustit debug perspektivu, která přepne rozložení oken Eclipse
  • Popis debug perspektivy v Eclipse
    • Okno zásobníku
      • Ukazuje, v jaké části programu se právě nacházíme
      • Jde o zobrazení části paměti zásobník obsahující rámce pro jednotlivé volání metod
      • Toto okno příliš nevyužíváme
    • Okno editoru
      • Okno se zdrojovým kódem
      • V debug perspektivě se zpravidla nepoužívá pro úpravu kódu
      • Zelený pruh určuje řádku, na které se program právě nachází při jeho krokování
      • Jsou vidět nastavené breakpointy
      • Nejdůležitější okno debuggeru
    • Okno se strukturou programu (outline)
      • Zobrazuje strukturu programu (jednotlivé třídy a metody)
      • Toto okno příliš nevyužíváme
    • Okno konzole
      • Okno, do kterého se vypisuje výstup programu
      • Uživatel zde rovněž zadává vstup programu, pokud je třeba
    • Okno sledování proměnných
      • Zde můžeme sledovat všechny proměnné a jejich aktuální hodnoty během krokování programu
      • Druhé nejdůležitější okno debuggeru
      • V záložce Breakpoints je seznam všech nastavených breakpointů
  • Ovládání debuggeru
    • V okamžiku, kdy se program zastaví na breakpointu, lze pokračovat v jeho krokování různými způsoby
      • Step Into - též klávesa [F5]
        • Provede jeden krok programu
        • Pokud je tímto krokem volání metody, skočí do této metody
      • Step Over též klávesa [F6]
        • Provede jeden krok programu
        • Pokud je tímto krokem volání metody, provede ji celou jako jeden krok (tj. do metody neskočí)
      • Step Return též klávesa [F7]
        • Provede všechny zbývající příkazy v metodě, vyskočí z ní a zastaví se na dalším řádku volající metody
      • Resume též klávesa [F8]
        • Provede všechny příkazy od aktuální pozice až k dalšímu breakpointu (nebo do ukončení programu) normálně (tj. bez krokování)
      • Terminate též [Ctrl]+[F2]
        • Ukončí provádění programu
    • Nastavení filtrů krokování (step filters)
      • Umožní omezit, do kterých metod je možné při krokování skočit
        • Např. nechceme, abychom se při krokování dostali do knihovních tříd a metod Java Core API
      • Zapnutí filtrů krokování (Use Step Filters též [Ctrl]+[F5])
        • Pokud je tlačítko zapnuté, filtry jsou použity a do vybraných balíků nevstoupí ani možnost Step Into
      • Sledování hodnot proměnných (okno sledování proměnných)
        • Záložka Variables
        • Automaticky zobrazuje platné lokální proměnné a jejich hodnoty
        • Pro zobrazení statických proměnných a konstant je nutné je zaškrtnout
          • => Java => Show Constants a Show Static Variables
      • Zobrazení aktuální hodnoty proměnné
        • Stačí kurzorem myši najet v okně editoru na proměnnou, která nás zajímá
  • Díky debuggeru přesně vidíme, co se v programu děje, jaké jsou hodnoty proměnných
    • Podstatně komfortnější, než kontrolní výpisy
    • Lze vyzkoušet na odhalení chyb v programu pro výpočet faktoriálu