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

> C++ výjimky

V tomto článku je vysvětleno zpracování výjimek v jazyce C++. Je tedy popsáno, co to vlastně výjimka je a jak ji lze zachytit. Dále je v článku popsáno, co se stane, když se výjimka nezachytí a nechybí ani krátká zmínka o úniku paměti.

28.2.2011 12:00 | Petr Sklenička | Články autora | přečteno 12685×

Jak již samotný název napovídá, výjimka bude něco, co se nestává příliš často, ale stát se to může. V programování se výjimkou rozumí nějaká neočekávaná událost, která může vést i ke zhroucení samotného programu. Pravděpodobně nejčastějším příkladem, na jakém se začínají vysvětlovat výjimky, je dělení nulou. Dejme tomu, že v našem programu očekáváme od uživatele zadání dvou čísel, které následně chceme mezi sebou vydělit. Když bude vše dle našeho očekávání, uživatel zadá například čísla 6 a 3, program vypočte podíl, vrátí číslo 2 a vše je jak má být. Problém nastane, pokud jako druhé číslo zadá nulu. To je pro nás výjimečná situace, neboť nulou dělit nelze. Proto je třeba tuto možnost ohlídat, aby nedošlo ke zhroucení programu. K tomuto účelu slouží právě výjimky.

Princip výjimek spočivá v tom, že část kódu, ve kterém může nastat výjimka, uzavřeme do bloku try. V případě, že v bloku try dojde k nějaké nečekáné situaci, řízení programu se předá do bloku catch a provedou se příkazy, umístěné v tomto bloku. Pokud k žádné výjimce nedojde, program bude pokračovat normálně dál s tím, že blok catch se přeskočí. Základní syntaxe v C++ tedy vypadá takto:

try
{
  // Nejaky kod, ktery muze zpusobit vyjimku
}
catch (Typ vyjimky)
{
  // Kod, ktery se provede pri vyvolani vyjimky
}
V předchozím odstavci jsme řešili problém dělení nulou. Nyní si ukážeme již přímo konkrétní kód, který bude dělit dvě čísla, přičemž děleni nulou bude ošetřeno.
int main()
{
  double a, b;
  cin >> a;
  cin >> b;

  try
  {
    if (b == 0)
      throw "Deleni nulou.\n";
    cout << a / b << endl;
  }
  catch (const char* exception)
  {
    cout << "Byla zachycena vyjimka - " << exception;
  }
  return 0;
}
V kódu se objevuje klíčové slovo throw. To slouží k vyvolání výjimky, čili pokud je b rovno nule, pomocí throw se vyhodí výjimka "Deleni nulou" a program přejde na blok catch, který očekává konstantní znakový ukazatel. Podotýkám, že použití mechanismu výjimek není v tomto případě nijak zvlášť nutné, neboť přímo tento případ by bylo jednodušší ošetřit prostou podmínkou, ale příklad slouží jako ukázka. Samozřejmostí je, že při psaní programů mohou nastat i jiné výjimky, než jen obyčejné dělení nulou. Může jich být opravdu mnoho, záleží především na povaze programu - problém může nastat v případě, že se nelze připojit k FTP serveru, že není možné číst ze souboru, nelze alokovat paměť apod. Snahou programátora by mělo být to, aby výjimky, které v jeho programu mohou nastat, co nejlépe ošetřil.

Vzhledem k tomu, že v programu většinou může dojít k více výjimkám, je možné napsat více bloků catch, přičemž každý bude mít na starost konkrétní typ výjimky. Jeden bude například hlídat zápis za konec pole, druhý připojení k internetu, třetí bude mít na starost chování jaderného reaktoru atd... Existuje však blok catch, který dokáže zachytit všechny výjimky.

try
{
  NejakaNebezpecnaFunkce();
}
catch (...)
{
  // Timto blokem je mozne chytit kazdou vyjimku
}
Čistě tento způsob však není přilíš vhodný, neboť je lepší každou výjimku ošetřit rozdílným způsobem, což v tomto případě nejde. Lepší tedy je napsat více bloků catch, a blok catch (...) dát až jako poslední, jako takový "záložní".

Výjimky mohou být také součástí tříd. Můžeme tedy vytvořit jiný typ objektu pro různé výjimky, které budeme chtít zachytit, přičemž samotný objekt může nést informace, týkající se vzniklého problému. Jestliže se výjimka, kterou chceme odchytit, vztahuje na něco, co se děje v nějaké třídě, bývá vhodné definovat typ výjimky jako vnořenou třídu. Pro jednoduchost můžeme uvažovat, že máme třídu MyStructure, v níž máme veřejně deklarovanou třídu WrongIndex. Třída MyStructure bude nějakým způsobem pracovat s polem (je vcelku nepodstatné, jakým způsobem). Jestliže zadáme špatnou hodnotu indexu, můžeme vyvolat výjimku, která bude typu WrongIndex. Blok catch(který se mimochodem často označuje jako handler) by vypadal následovně:

catch (MyStructure::WrongIndex&)
{
  // neco...
}
Třída MyStructure, společně s vnořenou třídou WrongIndex je k dispozici zde. Za zmínku ještě stojí, že ve výjimkách lze vytvořit jakousi "hierarchii" pomocí dědičnosti. Není tedy žádný problém vytvořit třídu výjimky, která bude dědit například z třídy WrongIndex. Stejně tak vytvoříme-li třídu, která bude dědit ze třídy MyStructure, tak tato nová třída zdědí i třídu WrongIndex.

Co se stane, když se výjimka nezachytí

Jak jsem již výše psal, nastane-li v programu něco neočekávaného, často tato situace vede k ukončení programu. Podívejme se na to ale trochu podrobněji. Nezachycená výjimka totiž nezpůsobí okamžité ukončení programu. Místo toho nejprve v programu dojde k zavolání funkce terminate(), přičemž tato funkce volá funkci abort(). Toto standardní chování je však možné v programu upravit, a to díky funkci set_terminate(). Deklaraci obou těchto funkcí (terminate() a set_terminate() je možné najit v hlavičkovém souboru exception. Budeme-li tedy chtít změnit chování programu při nezachycené výjimce, můžeme to provést takto:

#include <exception>
#include <iostream>
using namespace std;

void myFunction()
{
  cerr << "Nezachycena vyjimka.\n";
  cerr << "Program bude ukoncen.\n";
  exit(1);
}

int main()
{
  set_terminate(myFunction);
  int a, b, c;
  cin >> a >> b;
  if (b == 0) throw "Nezachycena vyjimka";
  c = a / b;
  cout << c;
  return 0;
}
V tomto případě, pokud bude hodnota b rovna nule, dojde k vyvolání výjimky. V programu ale není žádný odpovídající blok catch, který by výjimku ošetřil. Proto se zavolá funkce terminate(), která zavolá naší funkci myFunction. Co dělá tato funkce už není třeba komentovat.

Únik paměti

Nyní již víme, k čemu výjimky slouží a jak se používají. Nicméně tak jako všechno ostatní, tak i výjimky mají své nevýhody. S jejich použitím se zvětšuje velikost výsledného programu a program se stává o něco pomalejším. Výjimky si také příliš dobře nerozumí se šablonami, neboť šablony funkcí mohou vyvolávat různé výjimky v závislosti na konkrétní specializaci. Někdy také může nastat problém s dynamickou alokací paměti. V následující ukázce pochopíte, o čem mluvím.

try
{
    p = new int [100];
    if (myFunction() == false)
      throw "Nejaka vyjimka";
    /*
      Nejaky dalsi kod
    */
  delete [] p;
}
Zde může nastat problém. V případě, že funkce myFunction vrátí logickou hodnotu false, vyvolá se výjimka a řízení programu se předá odpovídajícímu bloku catch. Mimo to dojde k tomu, že ztratíme ukazatel p a blok paměti, na níž ukazatel ukazoval, zůstane nepřístupný. Tomuto problému se říká únik paměti. Jak tomuto úniku předejít? Poměrně jednoduše.
int *p = new int [100];
try
{
  if (myFunction() == false)
    throw "Nejaka vyjimka";

    delete [] p;
    cout << "Pamet uvolnena.\n";
  }
  catch (const char *ex)
  {
    delete [] p;
    cerr << "Vyjimka zachycena.\nPamet uvolnena.\n";
  }
Toto řešení má však tu nevýhodu, že zvyšuje možnost přehlédnutí dalších chyb. Závěrem se tedy dá říct to, že ošetření výjimek může být v některých programech velmi důležité, které ale na druhou stranu může vyžadovat velké úsilí. Proto je vždy vhodné používat výjimky s mírou a rozumem.

Verze pro tisk

pridej.cz

 

DISKUZE

Výjimky a dělení nulou 3.3.2011 15:08 Miloslav Ponkrác
L Re: Výjimky a dělení nulou 4.3.2011 19:47 Aleš Hakl
  L Re: Výjimky a dělení nulou 5.3.2011 12:07 Miloslav Ponkrác
2x uvolněná paměť 3.3.2011 18:29 Jaroslav Šmíd
  L Re: 2x uvolněná paměť 3.3.2011 22:26 Miloslav Ponkrác




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

13.9.2017 8:00 /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 – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).


Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

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ář

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

> Poslední diskuze

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

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

27.7.2017 12:24 / Jaromir Obr
Cteni/zapis

Více ...

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