Jak na pro­jek­ty v ja­zy­ce C

© Damig, 2004 – 2023
Koncept

Stručný průvodce Code::Blocks
Ladění

Postup při ladění v Code::Blocks

Pokud už jste nějaký debugger používali, umíte už používat i debugger v Code::Blocks. Pokud je tento debugger první, se kterým přicházíte do styku, proniknete do toho rychleji, když si přečtete také kapitolu Ladění. Jsou v ní popsány základní principy této činnosti.

Při ladění v Code::Blocks se držte tohoto postupu:

  1. Zkontrolujte, že projekt překládáte pro cíl Debug.
  2. Nastavte na řádek s kódem zarážku (breakpoint). Pro začátek je dobré začít prvním řádkem funkce main.
  3. V menu Debug spusťte příkaz Debug / Continue (jde spustit i ikonou nebo klávesovou zkratkou F8)
  4. Otevřete si okno pro sledování proměnných. V menu Debug → Debugging windows → Watches.
  5. Krokujte příkazem Next line (F7) po řádcích zdrojového textu a sledujte proměnné v okně Watches.
  6. Voláte-li na aktuálním řádku svou funkci a vy chcete skočit do ní, použijte příkaz Step into (Shift+F7).
  7. Dalším vyvoláním příkazu Debug / Continue necháte program běžet do další zarážky nebo do konce programu.
  8. Chcete-li přerušit vykonávání programu, použijte příkaz Stop debugger (Shift + F8).
Menu Settings → Environment… Máte-li ve svém systému na výběr více terminálových aplikací, můžete si zde vybrat, kterou bude C::B používat pro standardní vstup a výstup.
Zarážka se nastavuje klepnutím myší mezi číslo řádku a jeho začátek.
Kontextové menu nad zarážkou (pravé tlačítko myši) → Edit breakpoint… Zde můžete nastavit, za jakých podmínek se zde debugger zastaví.
Debugger po spuštění indikuje žlutým trojúhelníkem (šipkou), na kterém řádku je zrovna zastaveno vykonávání programu. Pro sledování proměnných je potřeba zobrazit okno Watches (Sledování).
Okno Watches automaticky zobrazuje lokální proměnné a argumenty aktuální funkce. Proměnné, které při předchozím kroku změnily hodnotu, se barevně zvýrazní.
Kromě lokálních proměnných lze v okně sledovat i výrazy. Jednou z možností je použít kontextové menu nad vybraným textem.
Další možností je napsat sledovaný výraz přímo do okna Watches. Pokud jde o složitější datový typ, lze kontextovým menu vyvolat dialog Edit watch…
V dialogu Edit watch lze upravit sledovaný výraz a zvolit formát, v jakém se budou data zobrazovat. Pokud se chceme dívat na výraz jako na pole, lze zde nastavit od kterého indexu a kolik prvků chceme sledovat.
V okně Watches lze sledovat základní datové typy, textové řetězce, struktury (viz *array) a jednorozměrná pole (viz array->data). Složitější datové typy je potřeba sledovat jako výrazy po složkách.

Známé problémy a jejich řešení

Ladění v různých verzích C::B

Poznámky k ladění v různých verzích Code::Blocks jsou popsány ve článku Debugging with Code::Blocks.

Cesty s mezerami a diakritikou

V názvech adresářů a vašich projektů nepoužívejte mezery ani diakritiku! Pokud se v cestě k vašemu projektu vyskytují mezery, je velice pravděpodobné, že některé nástroje, zejména debugger, nebudou schopny s vaším projektem pracovat. Viz poznámka na oficiálních stránkách C::B.

Sledování ukazatelů

Při sledování proměnných je potřeba mít na paměti, že debugger umí zobrazovat pouze jednoduché datové typy a struktury. U ukazatelů (a tedy i některých polí) se standardně zobrazuje pouze číselná hodnota adresy.

Chceme-li sledovat, na co ukazatel ukazuje, je potřeba debuggeru napovědět a sledovat výraz s dereferenčním operátorem (např. *ukazatel, místo pouhé proměnné ukazatel). Pokud ukazatel ukazuje na začátek pole, je potřeba nad sledovaným výrazem vyvolat kontextovým menu dialog Edit watch a zaškrtnout volbu pro sledování pole a zadat rozsah (nezapomeňte, že pole v C/C++ si obecně samy nepamatují svou velikost).

Pohledy na proměnné v seznamu argumentů a v seznamu lokálních proměnných nelze takto editovat. Vložte sledovanou proměnnou do okna Watches znovu jako sledovaný výraz a pak můžete jak používat dereferenční (i všechny ostatní) operátory, tak měnit kontextovým menu i samotný formát pohledu na data (Edit watch).

Sledování vícerozměrných polí

Sledování vícerozměrných polí představuje problém. Je třeba si uvědomit, že jazyky C/C++ takový typ neznají. Místo toho používají jednorozměrná pole, jejímiž prvky mohou být další jednorozměrná pole (řádky).

C::B nemá problém se zobrazením lokálních polí s konstantní velikostí. Problémem jsou ale dynamická pole, u nichž debugger nemá žádnou informaci o rozměrech. Při sledování je tedy potřeba sledovat vícerozměrné pole po řádcích (rozměr řádku se pak zadá editací pohledu Edit watch) nebo po samostatných prvcích.

Obecně se lépe sledují vícerozměrná pole vyrobená dynamicky na hromadě pomocí malloc či new (přes dvojité a vícenásobné ukazatele). Vícerozměrná lokální automatická pole (s rozměry specifikovanými pomocí proměnné) se sledují nejhůře. Musíte sledovat vhodně přetypovaný výraz.

Zvláštní problém představují vícerozměrná automatická pole, která předáváte jako argument funkce. Například parametr array funkce z ukázky 1 debugger zobrazit neumí. Při pokusu zobrazit jej jako pole vám debugger zobrazí hlášení "Cannot perform pointer math on incomplete types, try casting to a known type, or void *.". Nejde o problém C::B, toto hlášení pochází od GDB.

Řešením tohoto problému je přetypování sledovaného výrazu na ukazatel na pole pevné délky. Předpokládejme, že funkci voláme s polem o rozměrech 3 řádky a 2 sloupce, tedy printArray(3, 2, array) a pole array bylo skutečně vytvořeno s těmito rozměry. Budeme tedy sledovat výraz ((int (*)[2]) array). V našem případě je rozměr pole dvě, protože rozměr řádku pole (počet sloupců) je také roven dvěm (proměnná col). Pohled na tento výraz následně pomocí kontextového menu Edit watch… upravíme jako pohled na tříprvkové pole (počet řádků). Viz obrázek 10.

void printArray(int row, int col, int array[row][col])
{
  for (int r = 0; r < row; ++r) {
    for (int c = 0; c < col; ++c) {
      printf("%d ", array[r][c]);
    }
    printf("\n");
  }
}
Funkce, která má jako parametr automatické pole s rozměry deklarovanými pomocí proměnných. Funguje v ISO C99 a výš. Raději je nepoužívejte. V programech, které za něco stojí, způsobují více problémů než užitku. Vytvářejte pole dynamicky na hromadě (pomocí malloc), v C++ používejte šablony, například vector.
Sledování vícerozměrných automatických polí. Všimněte si, že výraz je sledován jako pole o délce 3 (Watch as array, Count = 3). Vlevo pak jde vidět výsledné zobrazení sledovaného výrazu.