Kurz Visual C++ (4.)


V první části dnešní lekce si povíme, jak předáváme programu parametry přímo z vývojového prostředí VC++. V druhé části si povíme něco o ladění programu.

4.1. Předávaní parametrů programu

Pokud program, který vyžaduje parametry příkazové řádky, spouštíte přímo z příkazové řádky, nenastává žádný problém, protože parametry jednoduše napíšete za jméno programu a každý parametr oddělíte mezerou. Co když ale chcete, aby takový program šel spustit (a ladit) přímo z VC++. Program, který vyžaduje parametry, obvykle nepracuje správně pokud žádné nedostane. VC++ implicitně žádné parametry nepředává, ale dá se nastavit tak, aby předával tytéž parametry jako na příkazové řádce.

A jak to provedeme?
Z menu Project vyberte položku Settings....  Objeví se tento dialog:

Přepněte se na kartu Debug a vepište do řádku Program arguments parametry, které budou při spuštění předány programu. V tomto případě máme otevřený projekt Functions, což je příklad z prvního kurzu o C/C++. Tento program vyžaduje parametry. Jsou to dvě kladné celočíselné hodnoty (v mém případě 5 a 6). Nyní, když spustíte program, všechny výpočty proběhnou správně a vypíše se správný výsledek.

 

4.2. Ladění programu

Každý programátor musí vědět, jak má ladit program. Často si myslíte, že program prostě musí fungovat, ale on nefunguje. Co s tím? Máte dvě možnosti. První je, že se budete dívat do kódu a doufat, že najdete chybu. V duchu si budete program pouštět. Druhá možnost je převedení vašich myšlenek do reality tím, že program budete ladit. Program se normálně spustí, ale vy budete moci sledovat, jak program pracuje krok po kroku, budete moci sledovat  obsah vybraných proměnných, budete  moci vidět obsah paměti, obsah registrů procesoru atd. Zkrátka ladění je velmi důležitá součást, bez které se jistě neobejdete.

Ladění programu je principielně v každém vývojovém prostředí stejné. V každém IDE se můžete dívat "do" proměnných atd.  Jiné je akorát ovládání Debugeru (ladiče). Již víte, že VC++ jsou dva režimy kompilace: Debug a Release. Jak z názvů vyplývá, ladit budete moci jen v režimu Debug a pak se budete modlit, aby v režimu Release vše fungovalo. Občas se stane, že v režimu Debug vše chodí a v Release nikoliv. To jsou ovšem málo pravděpodobné varianty a tím se zabývat nechci.

Důležité pojmy v oblasti ladění

Asi nejdůležitější pojem je tzv. Break point (neboli zlomový bod?). Break point (český překlad se nepoužívá) je skutečně bod někde v programu, kde kterém dojde k přerušení programu a předání jeho běhu vám, jakožto ladičům. Break point můžete umístit prakticky kamkoliv do vašeho kódu a jakmile se program dostane k tomuto bodu, je okamžitě přerušen. Vše si budeme zkoušet na příkladu z prvního kurzu o C/C++. Otevřete si tento projekt a kurzorem najeďte na řádek, kam chcete vložit Break point a pak stiskněte F9. Na začátku řádku se objeví červené kolečko, které označuje Break point. Break point můžete také vložit přes toolbar tlačítkem ruky:

Výřez programu s umístěným Break pointem, můžete vidět na následujícím obrázku:

Break point odstraníte stejně jako jste ho přidali: stiskem F9 nebo stiskem ruky na řádce, kde je break point vložen.

Poznámka: Když spustíte program v režimu Release a budete mít nastavené nějaké break pointy, VC++ vám oznámí, že tyto break pointy budou vypnuty. Jak už jsem říkal, v režimu Release ladit nelze, takže tento jev je normální.


Nyní můžete program spustit. Nastavený break point je hned na začátku programu, takže program se jakoby spustí, ale ihned je přerušen a fokus se vrátí na okno VC++, které se podstatně změní a může vypadat nějak takto:
 

Jak je možno vidět na obrázku, je tu spoustu nových okének, které si teď popíšeme. Okna lze libovolně přesouvat, měnit jejich velikost nebo zavírat. Zavřené okno znovu aktivujeme stiskem pravého tlačítka myši na přechodu z jednoho okna do druhého. Objeví se kontextové menu, kde vidíte zobrazené (zaškrtané) položky včetně toolbarů. Pravděpodobně nebudete využívat všechna okna najednou a tak si plochu uspořádejte podle svých potřeb.

Nyní si popíšeme jednotlivá okénka:

  1. Okno zdrojového kódu, kde byl program přerušen. Vidíte zde žlutou šipku, která ukazuje na aktuální pozici v programu (nyní je na break pointu). Touto šipkou můžete pohybovat ikonami, které jsou na Debug toolbaru vpravo:


    První ikonka v prvním řádku znovu pustí celý program a tudíž i ladění. Je k tomu, když během ladění změníte kód v programu, tak abyste nemuseli ladění ukončit a znovu pouštět. Rozdíl je ale v tom, že program se nepřeruší na prvním break pointu, ale hned na začátku celého programu, v tomto případě na vstupu funkce main().
    Druhá ikonka ukončí celé ladění, aniž by se na něco ptala.
    Čtvrtá ikonka je na zkompilování změněného kódu během ladění. Osobně tento postup příliš nedoporučuji. Podle mého názoru je lepší ladění ukončit a po změně kódu znovu spustit.
    Žlutá šipka jen zobrazí v okně 1 aktuální pozici v programu, tzn., že skočí na žlutou šipku v programu.
    Dále následuje čtveřice ikonek, které spolu úzce souvisí a jsou asi nejdůležitější:
        1. Pokud je aktuální pozice na nějaké funkci a klepnete na toto tlačítko, program se přesune do této funkce. Tuto volbu použijeme, pokud chceme vědět, co přesně se děje ve funkci, na které jsme. Klávesová zkratka je F11.
        2. Toto tlačítko naopak tuto funkci provede, ale vy to provádění nevidíte, zkrátka debugger ji přeskočí. Používáme ji tehdy, když stojíme na nějaké funkci, o které víme, že funguje a nezajímá nás co se děje uvnitř. Většinou jsou to funkce definované někým jiným. Klávesová zkratka je F10.
        3. Tato volba naopak opustí aktuální funkci a skočí o úroveň výš s tím, že provede zbytek funkce. Tuto volbu použijeme v případě, že chceme opustit aktuální funkci a nezajímá nás, co se děje dál. Klávesová zkratka je Shift+F11.
        4. Poslední ikonka provádí program od aktuální pozice žluté šipky a až do místa, kam je nastaven kurzor. Klávesová zkratka je Ctrl+F10

    Druhý řádek jen zobrazuje další okna debuggeru, které si popíšeme za chvilku.
     
  2. Další okno se nazývá Call Stack. Je to jakýsi seznam volaných funkcí v pořadí, ve kterém jsou volané. Ta poslední volaná je úplně nahoře. V našem případě vidíte, kdo zavolal naši funkci main(), byla to jakási funkce mainCRTStartup() a kdo zavolal jí? Byl to systém v podobě knihovny KERNEL32.DLL. Poklepem na funkci, se v okně 1 zobrazí místo odkud je volána následující funkce. Toto okno je důležité, pokud vůbec nevíte, kde se mohla stát chyba. Pokud se například pokusíte psát do cizí paměti, systém se okamžitě ozve a program se přeruší s hláškou buď Access vialotion (Násilné vniknutí - v tomto případě se myslí do paměti) nebo Unhadled exception (Neodchycená výjimka). Chybu odhalíte právě když se podíváte do okna Call Stack, kde vidíte funkci, která chybu způsobila.
     
  3. Výpis registrů procesoru. Pro ty, kdo neznají assembler, je to asi španělská vesnice.
  4. Toto okno souvisí s oknem 3. Je to surový obsah paměti systému, najdete tam i váš program v podobě čísel.
     
  5. Okno tzv. Variables neboli proměnných. Okno má tři karty, z nichž každá znamená pohled na proměnné z jiného hlediska.
        1.    První karta Auto zobrazuje proměnné, které se používají v blízkosti aktuální pozice v programu, pokud se přesunete o kousek dál, obsah okna se mění. Vidíte název proměnné a vedle hodnotu. Proměnné typu pole nebo objekt můžete dále rozbalit pomocí uzlu +. Můžete tak sledovat členské proměnné proměnné atd.
        2.    Druhá karta Locals, zobrazuje jen lokální proměnné aktuální funkce. Obsah tohoto okna se mění jen když vstupujete nebo opouštíte funkci.
        3.    Poslední kartu this, zatím nevyužijete, protože nepoužíváte objekty.

    Změna hodnoty proměnné
    Poklepáním na hodnotu proměnné, můžete hodnotu přepisovat za běhu programu. To se hodí zejména u dlouhých cyklů, kde potřebujete odchytit jen některé hodnoty řídící proměnné. Jednoduše tuto hodnotu přepíšete a skočíte dál v programu. Zádrhel je v tom, že se vynechají cykly, které přepsáním vynecháte.

    Příklad
    V našem případě vidíte na kartě Auto čtyři proměnné: parametry funkce main() a lokální proměnné k a n. Vidíte, co která proměnná obsahuje. Proměnné k a n nejsou inicializované, takže v nich jsou nějaká strašné čísla, ale to se brzy změní. Stiskněte jednou klávesu F10. Tak provedeme příkaz, na kterém je žlutá šipka a skočíme na další příkaz. Změní se se i obsah okna Variables. Máme zde jen dvě proměnné a to ty, které se použijí v přiřazení: k a argv. Proměnná k má stále tu hroznou hodnotu, ale po dalším stisku F10 se příkaz provede a program opět poskočí kupředu. Nyní vidíte, že hodnota proměnné k se změnila na 5 a zčervenala, to proto, abyste viděli, že se změnila. Takto můžete postupovat dál, dokud nenarazíte na funkci variace(), která je ukrytá v příkazu printf(). Na tomto příkazu stiskněte klávesu F11 a tak skočíte dovnitř této funkce. Program skutečně skočí do zcela jiného místa v kódu. Pokud vás funkce faktorial() nezajímá, můžete stisknout klávesy Shift + F11 a tak funkci variace() opustíte (funkce se ale provede). Nyní v okně Variables vidíte, co vrátila funkce variace(). Po dalším stisku F11, byste se dostali dovnitř funkce printf(), což není potřeba. Takže můžete pokračovat F10.
     
  6. Watches. Toto okno přímo vypisuje hodnoty zvolených proměnných. Většinou toto okno není potřeba, protože většinu proměnných odchytáte oknem Variables, ale občas se hodí, když chcete po celou dobu trvání programu sledovat určitou proměnnou.
  7. Output. Konečně poslední okno, je výstupní okno, do kterého se vypisují hlášky debuggeru. Existují funkce a makra, které do tohoto okna vypisují zprávy vámi určené. Nyní tam pouze vidíte, které dynamické knihovny systém načetl pro váš program.

Dobré rady:

A to je asi tak všechno. Tato problematika je docela rozsáhlá, takže kdybyste se chtěli na něco zeptat, stačí mi napsat.   

                                                                                                                                                                                                                                                                                                                   Jiří Formánek