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.
Využijte program valgrind. Jsou dva případy, kdy se těžko hledají.
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í.
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?
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 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
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 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 tvaru:
<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.
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).
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:
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.