LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> C++ a garbage collector

Často se mluví o tom, že C++ nemá garbage collector. Jenže ona to, přísně vzato, není ani trochu pravda. Už mnoho let tvrdím, že kdo v C++ ručně uvolňuje paměť a zavírá různé zdroje, ten neumí C++. Tento článek filozofuje s otázkou, zda C++ má či nemá garbage collector.

11.8.2014 19:00 | Miloslav Ponkrác | Články autora | přečteno 17449×

1. C++ a garbage collector

1.1. C++ není C s třídami

Jedna z nejhorších věcí, které může člověk dělat je, že chce předělávat jazyk či knihovnu k obrazu svému do cizí filozofie. Řada lidí posuzuje C++ jako C s třídami a přisuzují mu tytéž vlastnosti jako jazyku C. Jistě, že v C++ se dá programovat C stylem, ale je to obrovská škoda, protože C++ nabízí mnohem mnohem více. Využít možnosti C++ znamená v první řadě zapomenout C styl a nedělat věci v C++ tak, jak by je člověk dělal v C.

Pokud programujete v C++, využívejte jeho možností. C++ je velmi efektivní jazyk, umožňující mnohem efektivnější a rychlejší vývoj, než v C, aniž byste ztratili jedinou výhodu proti jazyku C. V C++ lze napsat program mnohem rychleji a efektivněji, než v C, přitom výsledek bude mnohem lépe udržovatelnější zdrojový kód oproti C a výsledná binárka bude stejně rychlá jako kdyby byla napsána v C. Abyste tohoto dosáhli, je třeba využívat možností a vlastností C++. Kdokoli má pocit, že C++ je pouze C s třídami, neříká tím o sobě nic jiného, než „já neumím C++“.

1.2. Cíle článku

V tomto článku se pokusím jednoduše zodpovědět na 3 otázky:

  1. Má C++ garbage collector pro automatické uklízení paměti?

  2. Potřebuje C++ garbage collector?

  3. Je účelné vybavit C++ garbage collectorem?

2. Má C++ garbage collector pro automatické uklízení paměti?

Správná odpověď je: Přijde na to.

C++ umožňuje vytvářet pointery, které jsou plně na zodpovědnosti programátora. A které programátor uklízí ručně a plně na své triko.

C++ umožňuje vytvářet pointery i objekty, které se automaticky dealokují a uklízejí bez starosti programátora.

Takže na otázku „Je pravdou, že C++ nemá garbage collector?“, nelze poctivě odpovědět, že C++ nemá garbage collector.

2.1. Návrhový vzor RAII

Programovací jazyk C++ pracuje na principu, že samotný C++ kompilátor velmi masivně už na úrovni jazyka C++ podporuje objektový návrhový vzor RAII (Resource Acquistion Is Initialization), nazývaný také SBRM (Scope Based Resource Management). Tento objektový návrhový vzor řídí životnost objektů, proto patří to do skupiny „creational patterns“.

Ve své podstatě je to vlastně „cé plus plus kovina“, protože je v ní cítit přesně ideologie C++. Tedy zobecňování principů až do maximální rozsahu, působení a důsledků, jaký je možný.

Dokonce právě uvědomění si základní vlastnosti programovacího jazyka C++, tedy, že se skládá v zásadě z několika jednoduchých základních principů a vlastností, které jsou dotáhnuté až do maxima, považuji za nejlepší způsob, jak se bezbolestně naučit C++. Pokud v C++ platí nějaký princip či vlastnost, pak pokud možno platí všude, na všechny typy i programátorské konsktrukce, kde je to jen trochu možné. Té vlastnosti říkám „cé plus plus kovina“, tedy obrovská vnitřní konzistence, logičnost a jednotnost celého C++ jazyka. Učit se C++ jinak, než pochopením jeho principů je velmi složité, učit se C++ pochopením jeho principů je velmi jednoduché a rychlé.

2.2. C++ dotahuje princip uklízení lokálních proměnných do absolutní dokonalosti

Člověk očekává, že ukončením podprogramu (či bloku programu) se automaticky odstraní a uklidí i lokální proměnné bez starostí programátora. Toto je ovšem ve většině programovacích jazyků nedotáhnuté, a není tomu plně tak. Vezmete-li si třeba Javu, .NET, C a mnoha dalších jazyků, nemůžete od nich očekávat to, že kompilátor zařídí také plný úklid lokálních proměnných. Uklízí se bez problémů proměnné typu integer, ale ne objekty. C++ dotáhl uklízení lokálních proměnných na plný automatický úklid a to pro jakékoli proměnné jakéhokoli typu. Tohle dotahování do konce je vlastně to, čemu říkám „cé plus plus kovina“, protože takto vzniklo skoro celé C++. Dotáhnutím principů do konce bez výjimek a nedotažeností.

Zaručený automatický úklid všech lokálních proměnných se právě nazývá RAII. Jednoduše stačí získat zdroj (paměť, soubor, grafický handle, cokoli) a uložit ho do proměnné, která ho bude vlastnit a při jejím zániku (voláním destruktoru) ho také uvolní. A tím se o to můžete přestat starat, protože zbytek zařídí C++ kompilátor, který bude uvolňovat zdroje automaticky v rámci rušení lokálních proměnných na konci oboru platnosti. A tomu se vznešeně říká RAII.

2.3. RAII versus klasický garbage collector

Ačkoli to vypadá jako nic moc, RAII je skutečně velmi dobrý garbage collector. Dokonce má další výhody:

  1. RAII uklízí nejenom paměť, ale všechny zdroje (třeba otevřené handly souborů, grafických prvků, síťové sokety, …).

  2. RAII je voláno okamžitě bez prodlení a přesně v čase, kdy zdroj přestává být potřeba.

  3. Proměnné a zdroje likviduje po skončení platnosti stejný thread jako jim dal vzniknout.

  4. Není třeba zastavovat program kvůli garbage collectoru jako v Javě, LISPu, a dalších.

Má samozřejmě i nevýhody:

  1. Je nepatrně pomalejší, protože RAII dealokuje okamžitě jedno po druhém, zatímco klasické garbage collectory dealokují naráz velké množství bloků paměti.

  2. Je třeba věnovat podpoře RAII pozornost při implementaci tříd.

2.4. C++ a uklízení sdílených proměnných

Dobrá, RAII tedy zruší již nepoužívanou paměť a zdroje lokálních proměnných. Ale co tedy uklízení paměti a zdrojů sdílených více tready nebo vranými jako návratové hodnoty?

Budete se divit, toto RAII také zvládne. Protože všechny případy automatického uklízení paměti se dají převést na uklízení lokálních proměnných. Kdy je třeba paměťový blok dealokovat? Když pointer na tento blok není obsažen v žádné proměnné, míněno v žádné lokální proměnné. Jakmile neexistuje lokální proměnná, která obsahuje adresu nějakého paměťového bloku, pak je třeba tento blok uklidit. A toto je možné pomocí RAII zařídit.

Nicméně zde je třeba použít chytré pointery z C++ standardní knihovny nebo podobnou funkcionalitu. Například std::auto_ptr nebo std::shared_ptr. Případně si napsat vlastní třídy.

Není tedy problém mít (jde o myšlenkový nástin, skutečný kód by byl odlišný):

MojeTrida * JinaTrida::getInfo()
{
  …
};

int main()
{
  JinaTrida a;
  a.getInfo();
  int x = a.getInfo()->getXParameter();
  MojeTrida * info = a.getInfo();
  int y = info->getYParameter();
  return 0;
};

A ačkoli se o to nestaráte, ve funkci main() nevznikne žádný memory leak, všechna paměť se uklidí a všechny instance třídy MojeTrida, které jsou vráceny metodou getInfo() budou automaticky uklizeny hned jak nebudou potřeba.

Jinak řečeno, v C++ opravdu je možné vracet z funkcí a metod pointery na objekty, a nechat C++ jejich automatické uklízení, aniž byste se o uklízení starali ručně.

2.5. C++ a garbage collecting

Znovu se ptám: „Má nebo nemá C++ garbage collector?“ Jak vidíte, odpovědět jde opravdu těžko. Oficiálně nemá, prakticky ale obsahuje věkerou funkčnost garbage collectoru, když o to budete stát a budete to potřebovat.

Už 10 let tvrdím, že pokud se v C++ někdo musí starat ručně o uvolňování paměti, tak neprogramuje v C++, protože ho neumí.

3. Potřebuje C++ klasický garbage collector?

V každém jazyce je dobré mít možnost garbage collectoru, jde-li to. Garbage collector je příjemná feature.

Na druhé straně garbage collector nemá jenom plusy.

3.1. Klasický garbage collector

Garbage collectorů je mnoho druhů, klasický garbage collector funguje na principu procházení všech identifikátorů v programu a uklízí pak ty bloky paměti, na které nevede žádný odkaz. A zde je kámen úrazu. Těžko bude garbage collector zjišťovat a procházet identifikátor, když program běží a identifikátory mění své hodnoty, protože programu musí stát a násilně být zastaven. A to se velmi často nehodí, přesněji, nehodí se to skoro nikdy. Pokud program dělá rychlostně kritickou činnost, pak garbage collector na chvíli zastavující program je poslední ranou do vazu. Ale i jinak, uživatel není rád, když program sekundu nereaguji na jeho kliknutí na tlačítko, protože zrovna se probral gc. To se různě eliminuje, ale je to jen zmírnění problému, nikoli jeho odstranění:

  1. Část práce se udělá za běhu programu inkrementálně.

  2. Paměťové bloky se rozdělí za několik generací, přičemž v nulté generaci jsou lokální proměnné, které se čistí okamžitě po skončení každého bloku. První a další generace pak chce už spuštění plnohodnotného gc.

  3. Opuletně se plýtvá s pamětí a gc se nespouští a nechává klidně hodiny i dny nevyčištěnou paměť v množství klidně stovek MB i několik GB.

  4. Jazyk má API, které umožňuje zakázat spuštění gc pro kritické fáze, nebo naopak doporučit spuštění gc, pokud je času dostatek.

Toto nejsou všechny problémy klasického gc. Další problém je uvolňování zdrojů. Gc se postará o uvolňování paměti, ale už ne dalších zdrojů. Programátor se o to musí starat ručně, pokud nemá docházet k plýtvání zdroji. A tak se to zase řeší nalepováky:

  1. Metody typu finalize().

  2. Metody typu dispose() v .NET.

3.2. Garbage collector typu čítač referencí

Cílem článku není kritizovat klasický garbage collector. Existují i gc, které uvolňují okamžitě a většinu výhod výše eliminují. Například čítač odkazů. Jenže ten má další nevýhody:

  1. Paměťová náročnost. Každá proměnné a každý blok má navíc 4 bajty na čítač odkazů. Dohromady je to obrovská paměťová náročnost.

  2. Problém s cyklickými odkazy, které nedokáže čítač referencí odhalit.

3.3. C++ a potřeba garbage collectoru

C++ jednoduše takové garbage collectory opravdu nepotřebuje. Jednoduše proto, že oblast používání C++ je tam, kde by vlastnosti klasického garbage collectoru či čítače referencí zničily to, co od C++ je žádáno.

Namísto toho proto C++ integrovalo RAII, které udělalo přesně to, co je třeba:

  1. Namísto procházení identifikátory a zjišťování seznamů nepotřebných bloků za běhu programu se všechno toto zařídí ve fázi kompilace programu. C++ kompilátor sám podle oboru platnosti lokálních proměnných vytvoří seznam už v době kompilace včetně automaticky generovaného kódu pro úklid paměti i zdrojů. Tím se neplýtvá cenným časem za běhu programu, stejně tak jako odpadá požadavek aby program měl přehled o všech proměnných za běhu programu.

  2. Namísto čítače referencí C++ kompilátor jednoduše detekuje místa už v době kompilace, kde má dojít k úklidu.

4. Je účelné vybavit C++ garbage collectorem?

Tato otázka už je mírně nadbytečná.

C++ má už v samotném jazyce vše potřebné pro automatické uklízení paměti a zdrojů v podpoře RAII. Jako vždy, C++ pouze nabízí, ale nevnucuje. Můžete klidně dělat program, kde budete celý životní cyklus paměti i zdrojů řídit sami, stejně jako můžete udělat program, kde uklízení bude probíhat zcela automaticky.


Článek daroval: Ing. Miloslav Ponkrác
www.ponkrac.net

Verze pro tisk

pridej.cz

 

DISKUZE

To je hlod 27.8.2014 11:19 Jan Němec
L Re: To je hlod 5.9.2014 15:18 Miloslav Ponkrác
  L Re: To je hlod 8.9.2014 11:28 Jan Němec
    |- Re: To je hlod 8.9.2014 16:26 Miloslav Ponkrác
    | L Re: To je hlod 22.9.2014 08:35 Aleš Hakl
    |   L Re: To je hlod 25.9.2014 03:11 Miloslav Ponkrác
    L Re: To je hlod 8.9.2014 16:29 Miloslav Ponkrác
      L Re: To je hlod 29.9.2014 15:35 Jan Němec
        L Re: To je hlod 1.10.2014 00:26 Miloslav Ponkrác
Díky za článek 4.9.2014 14:14 František Kučera
  L Re: Díky za článek 5.9.2014 15:34 Miloslav Ponkrác
    L Re: Díky za článek 9.9.2014 15:58 František Kučera




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

15.4.2017 15:20 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě IoT a radiokomunikace? Přijď na sraz spolku OpenAlt, který se bude konat ve středu 19. dubna od 18:30 v Šenkovně (Sokolská 60, Praha 2).
Přidat komentář

5.3.2017 19:12 /Redakce Linuxsoft.cz
PR: 23. března proběhne v Praze konferenci na téma Cloud computing v praxi. Hlavními tématy jsou: Nejžhavější trendy v oblasti cloudu a cloudových řešení, Moderní cloudové služby, Infrastruktura současných cloudů, Efektivní využití cloudu, Nástrahy cloudových řešení a jak se jim vyhnout.
Přidat komentář

27.2.2017 22:12 /František Kučera
Pozvánka na 137. sraz OpenAlt – Praha: Tentokrát jsme si pro vás připravili neobvyklou akci. Ve středu 1.3. v 17:30 nás přivítá sdružení CZ.NIC ve svých prostorách v Milešovské ulici číslo 5 na Praze 3, kde si pro nás připravili krátkou prezentaci jejich činnosti. Následně navštívíme jejich datacentrum pod Žižkovskou věží. Provedou nás prostory, které jsou běžnému smrtelníkovi nedostupné!
Po ukončení prohlídky se všchni odebereme do hostince U vodoucha, Jagelonská 21, Praha 3 pochutnat si na některém z vybraných piv či dát si něco na zub. Rezervaci máme od 19:30, heslo je OpenAlt.
Ale pozor! Do prostor datového centra máme omezený přístup, dostane se tam pouze 10 lidí! Takže kdo přijde dříve, ten má přednost, a občanky s sebou! Kdo nebude chtít na prohlídku datového centra, může se pomalu přesunout do hostince U vodoucha a u nepřeberné nabídky piv počkat na ostatní.
Přidat komentář

18.1.2017 0:49 /František Kučera
Členové a příznivci spolku OpenAlt se pravidelně schází v Praze a Brně. Fotky z pražských srazů za uplynulý rok si můžete prohlédnout na stránkách spolku. Příští sraz se koná už 19. ledna – tentokrát je tématem ergonomie ovládání počítače – tzn. klávesnice, myši a další zařízení. Také budete mít příležitost si prohlédnout pražský hackerspace Brmlab.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

1.8.2017 7:32 / Cassidy
structural consultants

30.7.2017 11:12 / Jaromir Obr
Národní znaky

27.7.2017 12:24 / Jaromir Obr
Cteni/zapis

26.7.2017 21:12 / Jaromir Obr
Podminka

15.6.2017 9:34 / Ondřej Havlas
php,

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze