Semestrální práce

Tipy a triky

Cílem této konzultace bylo ukázat vám jak jednodušše vytvořit dokumentaci pomocí Doxygen komentářů a případně vás navést na to, kde a jaké informace hledat k vaší semestrální práci.

Nejčastější chyby

Jak si ověřit potenciální memory-leaky?

Využijte program valgrind. Jsou dva případy, kdy se těžko hledají.

Server vypínaný pomocí CTRL+C

Pokud ukončíte program pomocí CTRL+C vyšle se do vašeho programu signál, který v základní podobě přeruší program a tím pádem nedojde k uvolnění paměti. Abyste si mohli ověřit uvolnění, stačí naimplementovat tzv. signalHandler.

 int * pole;

void signalHandler ( int )
{
  delete [] pole;
  exit( 0 );
}

int main ( void )
{
  signal( SIGTERM, signalHandler );
  signal( SIGINT, signalHandler );
  pole = new int [];
  while ( true ) {}
  delete [] pole;
  return 0;

Všimněte si, že daná proměnná musí být globální. Tudíž pokud si chcete ověřit, že tam žádné memory-leaky nemáte. Naimplementujte si tento jednoduchý signal handler, v kterém provedete uvolnění paměti (resp. vše co by se mělo provést před skončením programu). Toto vypínání není zcela korektní, ale pro vaše potřeby bude vyhovující.

NCurses aplikace

Pokud používáte ncurses, či některé jiné knihovny, tak vám valgrind bude nejspíš hlásit neuvolněnou paměť, což je v pořádku. Ale jak přijít na to zda jsou memory-leaky vaše nebo ncurses?

  1. Vysledovat z valgrind logu původce memory-leaku (vždy by se měl objevit původce v ncurses knihovnách)
  2. Naimplementovat 2 různá rozhraní. Chápejte ncurses vs. console jako dvě různá rozhraní pro komunikaci s uživatelem. Poté můžete mít základní třídu jako BaseUserInterface a dva potomky ConsoleUserIn­terface a NCursesUserIn­terface. Pokud v ncurses rozhraní nebudete alokovat žádnou paměť (obecně se zde nebude vyskytovat klíčové slovo new) a zároveň při použití ConsoleUserIn­terface nemáte žádné memory-leaky, pak nutně musí mít všechny původce v ncurses knihovnách. Zároveň máte další prvek polymorfismu.
  3. Pokud používáte nějakou knihovnu, měli byste vědět, kde mohou být problémy. Podobně jako při volání funkce fopen je nutné zavolat fclose, tak u knihoven bývají implementované funkce pro uvolnění paměti, kterou vytvořili voláním jiné funkce.

Dokumentace

Dokumentace je povinnou součástí semestrální práce, nemusíte povinně využít systém Doxygen, ale je to velmi doporučováno. Ušetří vám to práci a je to jednoduché. Trik je v použití tzv. dokumentačních komentářů, které se od klasických liší použitím /** Doxykomentář */ dvou hvězdiček místo jedné. Doxygen umožňuje použití dalších parametrů, které umožňují dokumentovat parametry metody, návratové hodnoty či vyhazované exceptiony.

Doxygen umožňuje dokumentovat třídy, metody, konstanty, členské proměnné. Obvykle se dokumentuje pouze v hlavičkových souborech. To jsou totiž ty, které sdílíte s dalšími programátory. Umožňuje generovat grafy závislostí a dědičnosti. Pro to je potřeba mít uvedený Doxyfile (případně si ho správně nastavit) a pro vygenerování už pouze stačí provést doxygen Doxyfile. Ukázku můžete najít na školním GitLabu v repozitáři bi-pa2-uschovna.

 /**
 * Metoda vytváří správný objekt (server nebo klient), dle zadaných parametrů a zároveň vytváří socket
 *
 * @param[in] typ Typ aplikace, která se má vytvořit
 * @param[in] adresa IP adresa, ke které se má klient připojit nebo na které má server poslouchat
 * @param[in] port Port, ke kterému se má klient připojit nebo na kterém má server poslouchat
 *
 * @return V případě úspěchu vrací instanci aplikace, při chybě vrací NULL.
  */
static Aplikace * vytvorAplikaci ( const char * typ, const char * adresa, const char * port ) 

První řádka slouží jako krátký popisek, podrobnější informace píšeme dál. Navíc můžete využít Doxygen tagy. Do popisu nepište typ, to si Doxygen zjistí sám, ale slovní popis. Následující tabulka uvádí nejčastěji používané tagy, seznam všech tagů najdete na Doxygen manuálové stránce

Nejčastěji používané Doxygen tagy
Tag Popis
@param[in] <promenna> <popis> vstupní parametr
@param[out] <promenna> <popis> výstupní parametr
@param[in,out] <promenna> <popis> vstupně-výstupní parametr
@return <popis> návratová hodnota
@throw <class> <popis> třída vyhazuje <class> vyjímku za určitých podmínek popsaných v <popis>

Makefile

Makefile slouží k sestavení jednotlivých object-filů a následně spustitelného souboru. Ukázku opět můžete najít na Gitlab. Makefile se skládá z tzv. pravidel, které jsou v následujícím tva­ru:

 <vystup>: <zavislost1> <zavistlost2> <zavislost3>
    příkaz který vytvoří <vystup> (k sestavení může použít pouze uvedené závistlosti) 

V Makefile se dají použít určité zástupné znaky jako jsou proměnné:

 COMPILER=g++

a.out: main.cpp
    $(COMPILER) main.cpp -o a.out 

Nebo také zástupné symboly za <vystup> a závislosti.

Zástupné symboly
Symbol Význam
$^ všechny závislosti
$< první závislost
$@ <vystup>

Pokud sestavujeme například .cpp soubor do .o object filu, pak závislost je samotný cpp soubor a také všechny hlavičkové soubory, které includuje i nepřímo (jinak řečeno, na kterých závisí). Tuto závislost může vygenerovat například g++ -MM, ale to neznamená, že dané závislosti jsou 100% správně (v 90% bývají). Zamyslete se, co skutečně znamená ona závislost. Pokud includujete hlavičkové soubory, které nepotřebujete, pak budete mít špatné závislosti a celý proces pozbývá smyslu.

Poté můžete sestavovat celý projekt po jednotlivých object filech a nakonci je jen „slinkovat“ dohromady, což znamená, rychlejší kompilaci v případě drobné změny (samozřejmě pokud jsou dobře závislosti, tedy nespoléhejte slepě pouze na -MM, je třeba závislosti chápat, a projděte si svoje zdrojové kódy).

Umělá inteligence

Pokud máte naimplementovat škálovatelnou umělou inteligenci, tak ve většině případů stačí udělat hloupou a chytrou. Jakým způsobem je rozlišit to nechám na vás. Pokud máte ambice na nějakou lepší umělou inteligenci, doporučuji např. předmět BI-ZUM, případně by vás mohli zajímat pojmy jako:

Tipy a triky k obhajobě

Obsah

Neblokující čtění

Jak v konzoli zajistit neblokující čtení? K tomu vám může pomoct kód, který najdete na http://www.cplusplus.com/…nices/18395/. Pravděpodobně bude nutné přidat ještě hlavičku #include <termios.h>, která by měla být dostupná na image, co se nachází na eduxu.