Registrace nového uživatele     Návod     Kluby     Archív  Lopuchu     Lopuch.cz  

Náš Lopuch Vám
vytře zrak

Lopuch.cz

Jméno:
Heslo:
Podpora LCD:
 
Archiv klubu C, C++ [ŽP: neomezená] (kategorie Programování) moderuje Šéf Lopuchu.

Články

Jak bezpečně ukončit vlákno z DllMain
FastAllocPool - urychlení častých alokací a dealokací
Akce a zpráva jako objekt
Tuply v C++
Efektivní alokátor malých objektů a tady druhý a třetí díl
Šablony: Být vládce kvalifikátorů
Vracíme z funkce objekty
Základy komunikace mezi procesy (ve Windows)
Multiple Interface a Instance Factory
Multithreading v C++ (ve Win32)
  Nastavení klubu     Nastavení práv     Homepage     Anketa     Přítomní     Oblíbené     Lopuch     Kategorie  
autor: 
text: 
vyplnit a 
Help
   
[ 280 ] <Novější  <<<Nejnovější  Nejstarší>>>  Starší>  
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 30.6.2006 21:42  500
Bredy [499]: Moment, ale co kdyz je otevriSoubor cizi API funkce? Po te tezko muzes chtit, aby volala osetriChybu. Nebo si na kazdou API funkci budes psat wrapper a povinne volat jenom ten? To zase prijde ponekud uchylny mne.
Ano, neni nic hezkeho, kdyz Ti odnekud vypadne neosetrena interni vyjimka. Stat se to muze a stavat se to bude. Jenom tvrdim, ze v tymovem prostredi se tomu v pripade vyjimek predchazi lepe nez v pripade explicitniho osetrovani vseho, co se v danem miste kdy muze stat.
Logovani do souboru je vec hezka, tu ja velmi podporuju, napriklad hned v konstruktoru te vyjimky se da lognout. Ale neni to zpusob, jak situaci vyresit, jeste je taky potreba vyhodit nejakou dostatecne hezkou hlasku uzivateli, coz prave udelas velmi hezky napriklad tak, ze vyhodis pro tyto ucely definovanou vyjimku s kodem chyby, tahle vyjimka probubla pres veskera zanorena volani (vcetne ruznejch remote volani pres enterprise beany a podobne) az ke klientovi, ten si precte kod chyby, mrkne do property souboru (respektive ten ma uz samozrejme davno nactenej) a zobrazi uzivateli hezky okynko, ze je patek odpoledne a to uz by stejne nemel pracovat, tak at neotravuje.
bredy 30.6.2006 21:34  499
KdokolivNo jednak predpokladam ze otevriSoubor bude take volat funkci osetriChybu nez vrati false (coz je prave princip doprednych výjimek neboli "schranky chyb". - jak jsem napsal osetriChybu může být rozhraní, na kterým bude viset objekt, který může například chyby zapisovat do pole)

Co se práce v týmu týče, tak není nic hezkého, než když ti odněkud vypadne neošetřená "interní" výjimka. Například onehdy se mi stalo, že odněkud zevnitř jádra DirectX8 najednou vylítla výjimka "int". Nikdo nevěděl proč, a přišlo mi docela divný ji odchytávat. Co mě je po tom, že v jádře DX je něco neošetřeného....

Prostě argument "že na něco zapomenu" u mne neobstojí a nemyslím si, že výjimky jsou tím lékem. Naopak si myslím, že mnohým programátorům způsobí, že si budou mylně myslet, že jsou.

Mimochodem, v naší firmě používáme na chyby prastaré řešení LogF, což je něco jako printf do log souboru. Když něco nefunguje, prostě se prohlídně log soubor a většinou se přijde na to co se děje. Já vím, že to není nic moc, ale jen taková je realita. (nejsem zastáncem takového ošetřování chyb)
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 30.6.2006 21:25  496
Ano, ja souhlasim s tim, ze kdyz si tohle vsechno napises sam, tak to bude rychlejsi (co do behu programu), o tom se nikdo nebavi. A kdyz opustis C a napises to v assembleru, tak to bude jeste rychlejsi. Tady jde o to, ze kdyz tam ty volani se spolecnym osetrenim chyby nebudou tri, ale bude jich tam patnact, tak se ve svem zpusobu zacnes upisovat k smrti. Navic typicky skutecne nebudes moct jenom zavolat if (!otevriSoubor()), protoze taky treba budes chtit mit v nejake promenne, kterou predas tomu osetrovani, ulozene trochu lepsi upresneni toho, co se pri otvirani souboru stalo, takze tam skutecne bude neco jako int flagChyby = otevriSoubor(); if (flagChyby != NO_ERROR) osetriChybu(flagChyby);, tedy dalsi silene dlouhe kusy kodu (pokud to samozrejme nebudes delat pres nejakou globalni promennou, coz taky neni moc hezke.
Ale v principu jde o to, ze pri tomhle postupu osetrovani kazde chyby v kazdem miste, kde muze nastat, drive nebo pozdeji na neco zapomenes, je to prakticky nevyhnutelne. A kdyz ne Ty, tak nekdo jiny, kdo dela na temze projektu. Takze mozna Ty sam si veris natolik, ze takovehle chyby neudelas a na nic nezapomenes (a ziskas par pomerne zanedbatelnych promile vykonu, pokud tedy zrovna nepises soft pro jadernou elektrarnu, kde by to mohlo hrat vetsi roli), ale pro vetsi tymovy veci je mechanismus vyjimek (plus nejake interni guideliny o tom, jak jej pouzivat) nedocenitelny.
bredy 30.6.2006 21:15  495
mimochodem to co jsem napsal je rychlejsi, zabere mene instrukci a hlavně nezabira cas, pokud chyba nenastane (což výjimky ano)
bredy 30.6.2006 21:14  494
kdokolivNemáš pravdu. "nejaky_jednotny_kod_osetreni" das do nejake funkce, kterou budes volat pred returnem, nebo s returnem
if (!otevriSoubor()) return osetri_chybu("nelzeotevri");
if (!ctiData()) return osetri_chybu("nelzecist");
zavriSoubor();

funkci osetri_chybu implementujes tak, ze za vsech okolnosti vraci false.

Idealne osetreni bude takove, ze zavolas nejake rozhrani, ktere si zdedi aplikace chtejici osetrovat chyby po svem. Pokud to neudela, bude tam nejaky defaultni printf a abort.
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 30.6.2006 19:20  493
Bredy [489]: Jenze uz to neni ekvivalentni v tomhle pripade:
try {
otevriSoubor();
ctiData();
zavriSoubor();
}
catch (IOException e) {
nejaky_jednotny_kod_osetreni
}
vs.
isOK = otevriSoubor();
if (!isOK) {
nejaky_jednotny_kod_osetreni
return;
}
isOK = ctiData();
if (!isOK) {
nejaky_jednotny_kod_osetreni
return;
}
isOK = zavriSoubor() {
nejaky_jednotny_kod_osetreni
}
bredy 30.6.2006 18:50  492
Johny_GJo, to jsem právě psal. Mám cosi jako schránku chyb. Pokud funkce narazí na chybu, oznámí jí (voláním nějakého rozhraní), a vyskočí s "false". V závislosti na tom, jestli tě to zajímá nebo ne si to přečteš. Vícenásobné chyby (hlášené z ruzných levelů) se mohou štosovat v nějakém stacku, aby se neztratilo nic.
johny_g Johny_G - Relaxační terapie pro lopušáky ZDARMA! 30.6.2006 18:47  490
Jo, jo. Je jasný, že když o něco jde, tak je potřeba uživatele informovat o tom, kde se to zvrtlo. U běžné aplikace by mě docela dožralo, kdyby mi to místo mých dat nahodilo nějaká náhradní a ani bych nevěděl proč. Ovšem když to praktikuji u hry, která načítá nějaké to nastavení a paměť umělé inteligence, tak mi příjde zbytečné zatěžovat uživatele hláškou, protože by s tím stejně nic nenadělal. V tomto případě je to pohodlnější i pro programátora, i pro hráče.
bredy 30.6.2006 18:34  489
Jogny_GNo teď budu vypadat jako nějaký profesor nebo učitel. Ale myslím si, že bez ohledu na to, zda to potřebuješ vědět nebo ne by nějaká čtecí funkce měla vydat nějakou informaci, proč čtení selhalo. To že ji pak zahodíš je věc knihovny, kterou ji volá.

Mimochodem, I/O se to dělá většinou pomocí failstate. Objekt který čte / zapisuje se při první chybě přepne na failstate a všechny další operace automaticky selhávají, přičemž kód chyby je zapsaný jen jednou (poprvé).

Mimochodem, je fuk, jestli se chyba nahlásí výjimkou nebo jinak.
try
  {
   CtiHlavniData();
  }
catch (Chyba e)
  {
   CtiNahradniData();
  }

nebo

if (!CtiHlavniData()) CtiNahradniData();
johny_g Johny_G - Relaxační terapie pro lopušáky ZDARMA! 27.6.2006 19:58  488
Bredy [475]: Tak úplně ti nerozumím - když používám výjimky já, tak jsou to zpravidla místa, kde je mi úplně putna, k jaké došlo chybě. V každém případě postupuji stejně. U mě je to v 90% při čtení ze souboru, takže když se něco podělá, tak potřebuju načíst alespoň záložní data, aby mi to nezbořilo celý program. Je mi celkem fuk, zda byl soubor nečitelný, měl neplatný formát, nebo tam vůbec nebyl. V každém případě si potřebuju místo dat ze souboru nahodit nějaká rezervní.
bredy 27.6.2006 11:33  487
Exception házené dopředu
void A()
{
  class CatchForwardedException: public ForwardedExceptionHandler
  {
    public:
      virtual bool OnException(const IException *e)
      {
        ... delej neco s e;
        return CallNextExceptionHandler(e);
      }
  };
  
  CatchForwardedException hnd; //construktor ForwardedExceptionHandler instaluje handler do seznamu handleru
  if (B()==false) return ; //rizeny navrat, exception je resena v 
handleru
/* nebo 
  B();
  if (hnd.catched()) return;
*/
  ...
  ... 
  }
}

bool B()
{
  ForwardedException::Throw(new SomeException(...));
  return false; //neuspech.
}
bredy 27.6.2006 11:27  486
huhVlastně ještě jinak. Jedna věc, která mi vadí u vyjímek je onen stack unwind. Systém odchytávání výjimek mi nevadí, problém je v tom, že malokdy bych měl program kde funkce A() volá funkci B() a nic jiného nedělá. Z pravidla něco dělá, minimálně vytváří nějaké objekty, alokuje paměť atd.

To co píšeš právě řeším onou dopřednou výjimkou, kdy se výjimka vyhodí, ale nedojde ke stack unwind. Místotoho dojde k řízenému návratu z funkce Z() do funkce A(). To že normální programátor "zapomíná" předávat důvod chyby je jiná věc.

Ono je někdy zajímavé sledovat nejen důvod chyby, ale i vývoj chyby, intepretaci chyby každou úrovní. Totiž sice je pěkný, když podle Kdokoliva se dozvím že došlo místo na disku, ale taky se můžu dozvědět hlášku "sector not found", pokud by např. neúspešné hledání volného místa řešilo výjimkou. Interpretaci chyby totiž řeší až nějaká další úroveň.

V našem příkladu funkce Z() způsobí chybu, jejiž interpretaci však zná funkce U(). Ano, řešit se to dá odchytem výjimky ze Z a hozením výjimky z U().

Abysme se neztratili. Mnohem radši mám zákon "padajícího lejna". Když nastane nějaká výjimečná situace, oznámím to vejš ať si s tím poradí. Jako zaměstnanec firmy nejdou s každým problémem za šéfem. Ani není mou povinností zjišťovat, kdo má tyto problémy na starosti.
huh huh 27.6.2006 11:11  485
Vlastně jednou z hlavních myšlenek výjimek je, že hierarchie ošetřování
chyb je dost často mnohem jednodušší než hierarchie volání metod
(posílání zpráv).
Ty se totiž dost mýlíš, když tvrdíš, že volající funkce tu situaci neřeší. Ale to právě není pravda. On jenom neobsahuje žádný explicitní kód a to je ta výhoda. Situaci nicméně řeší naprosto korektně: zruší lokální objekty a pošle výjimku dál.

Další velká výhoda výjimek je jejich vnořování, kdy nedochází ke ztrátě informace. Jestliže používám knihovnu lib1, která používá knihovnu lib2, tak se při chybě v lib2 typicky dozvím, že selhalo volání lib2, ale už nikoli konkrétně co (to by lib1 musela mít příznak pro každou chybu lib2). U výjimek sice také typicky lib1 vyvolá vlastní výjimku, ale do jejího objektu umístí objekt výjimky, který dostala z lib2 a já jsem schopen tak zjistit, co selhalo konkrétně.
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 27.6.2006 11:10  484
Bredy [483]: Predstav si, ze mas nejakou funkci a(), ktera obsluhuje nejakou udalost od uzivatele, ta behem toho vola funkci b(), ta c() a takhle dal budes mit 25 (nebo kolik) zanorenych volani az po funkci z(). Ta provadi nejakou IO operaci, ktera muze selhat a vyhodit vyjimku. Funkce y() (ktera vola z()) tuto (a pripadne jine) vyjimku odchyti a vytvori nejakou vseobecnou ApplicationException, ktera ma v konstruktoru nejaky kod chyby a tu vyjimku, ktera konkretne nastala. Tuto vyjimku vyhodi funkce y() a vsechny funkce od x() az po b() se o to vubec nestaraj, takze vyjimka probubla az k a(). Funkce a() tuto vyjimku pochopitelne (jako kazdy jiny handler) odchytava, koukne se na kod chyby, podle kodu chyby nacte z resource pro patricny jazyk spravnou chybovou hlasku, kterou zobrazi uzivateli (treba "doslo ti misto na disku, vole"). Neni sebemensi duvod, aby funkce b() az x() odchytavaly ApplicationException, ty ji proste vyhazuji o uroven vyse, protoze nejsou zodpovedny za to, aby ji osetrovaly (o osetreni se stara nejvyssi funkce, ktera ma jako jedina pravo uzivateli neco oznamovat).
bredy 27.6.2006 10:59  483
KdokolivTohle bych potřeboval trošku přiblížit. Kdy je nežádoucí chybu řešit? Řešit se má každá chyba. Pokud je volání funkce smluvní vztah mezi volajícím a volaným, pak musí být ve smlouvě napsáno, za jakých podmínek od smlouvy odstoupit. Pak volající musí tuto situaci řešit.

[ 280 ] <Novější  <<<Nejnovější  Nejstarší>>>  Starší>  

(c) 2001-2011 Lopuch.cz   
Kontakt