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

Když diskuse,
tak s Lopuchem

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ší>  
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.
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 27.6.2006 10:52  482
Bredy [481]: Tak to prave neni pravda. Existuje rada dobrych duvodu, kdy nejaka funkce pouze o sobe rika, ze v ni muze vzniknout ta a ta chyba, a zaroven v miste volani teto chyby neni duvod (a mnohdy je to dokonce nezadouci) tuto chybu resit.
bredy 27.6.2006 10:49  481
huhVíš co, věřím, že ti to ulehčí hodně práce. Ale na druhou stranu, tvůj příklad je takový zrovna divný. Ukazuje to, že není známo, která funkce má zodpovědnost za chybu. Když ve funkci i vznikne chyba, měla by to oznámit funkci h, která si požádala o nějakou akci, která nemůže být splněna. Funkce i splnila svou zodpovědnost nyní je zodpovědnost na funkci h. Atd. Tady je to krásně napsaná, ale co když je každá funkce v jiném modulu, nebo v jiném objektu? To že funkce h neřeší zodpovědnost za chybné ukončení funkce i je chyba v návrhu programu. Dávat pak catch do každé úrovně ti pak naopak zabere víc času.
huh huh 27.6.2006 10:35  480
No pro mě je mnohem důležitější můj čas, který strávím psaním kódu. A ten mi dovolují výjimky výrazně zkrátit. Nemluvě o tom, že když ji zapomenu obsloužit, tak se program relativně korektně ukončí, možná i se smysluplnou hláškou. U klasických metod obsluhy chyb typicky padne někde jinde na něčem jako chybný přístup do paměti nebo tak něco.

Představme si třeba takovéto volání metod
void f() {
   g(); // zde chci osetrovat chyby
}
void g() {
   h();
}
void h() {
   i();
}
void i() {
   // zde muze nastat chyba
}

Pokud mam vyjimky, staci typicky upravit f a i:
void f() {
   try { g(); }
   catch(Exception& ex) { ... }
}
void i() {
   if (chyba) throw Exception("...");
}    

Pokud je nemam, musim v kazde funkci kontrolovat, jak dopadla:
void f() {
   g(); 
   if (nastala chyba) { ... }
}
void g() {
   h();
   if (nastala chyba) { return; }
}
void h() {
   i();
   if (nastala chyba) { return; }
}
void i() {
   if (chyba) { nastav priznak chyby }
}

Staci jednou zapomenout a je to v pytli.
mpts mpts Je to jinak, ba přesně naopak! 27.6.2006 10:18  479
Já neužívám výjimky v konstruktorech (také přepnu na failstate), jinak ale je užívám běžně, jen se snažím ošetřit je co nejníže. Pravdou však je, že jsem nikdy nedělal nic, co by bylo time-critical.
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 27.6.2006 10:14  478
Bredy [477]: No ono je pak hlavne taky otazka, jak se chovaji knihovny, ktere pouzivas. Ja prave C++ knihovny (at uz nejake standardni, nebo casto pouzivane) vubec neznam, tak to nemuzu posoudit. Ale v Jave se proste s vyjimkami pocita a rada knihovnich (a posleze i pak 3rd party) funkci je vyhazuje, takze Ti proste nezbyva, nez je odchytavat (protoze s vyjimkou runtime vyjimek to jinak neprelozis), pripadne mnohdy i treba posilat dal.
To, ze je s vyjimkami vznikajicimi v konstruktorech, velka sranda, to je fakt. Ale v Jave to proste vsechno resi prekladac. Jak, to nemam predstavu. Ze to asi v mnoha mistech povede k nejakemu zpomaleni, to asi jo. Ale v Jave se tim nejen nemusis zabyvat, ale predevsim ani nemuzes, ber, nebo bez jinam. :-)
bredy 27.6.2006 10:08  477
KdokolivZa normálních okolností dochází k destrukci objektů, ale za normálních okolností ví překladač jaké objekty během práce vznikly a tedy je třeba je destruovat.

V případě vyjímky je situace horší. K výjimce dojde někde uprostřed bloku, kde jsou některé objekty zkonstruovány a jiné ještě nejsou. Pak se musí při stack unwind provést destrukce pouze těch objektů, které jsou zkonstruovány. Nojo, ale jak to ten handler pozná?

Pokud se v C++ (myslím teď MSVC) povolí používání exceptions (považují za dobrou funkci možnost to vypínat), pak překladač obohatí každý objekt vytvořený v zásobníku o příznak (int), který říká, zda je objekt již zkonstruován či nikoliv. Kdykoliv program projde konstuktorem toho kterého objektu, jeho příznak změní. Totéž projde-li destruktorem. Exception handler přeložen tak, že postupně projde všechny objekty na zásobníku a ty které mají příznak nastavený destruuje.

To není jediná věc, která je v programu navíc. Na začátku každé funkce (opakuji každé, byť má jeden řádek kódu, ale musí konstruovat nějaký objekt) je vložen blok několika instrukcí, které si poznamenávají adresu exception handleru následující funkce (bloku). Tota informace je uložena do globální proměnné v TLS (thread local storage). Původní hodnota je uložena do stacku. Před ukončením funkce se provede zase zpětná rošáda.

Dalším problémem jsou vyjímky v konstruktorech. Obecně se považuje objekt za nezkonstruováný, pokud v něm vznikne vyjímka. Výjimka v konstruktoru nezavolá destruktor i když by došlo k výjimce na konci konstruktoru (zavolá se jen destruktory member proměnných a base tříd). Největším problémem je výjimka v destruktoru. Je-li hozena během stack unwind, je tato výjimka zachycena v nějakým globálním handleru a ten nemá jinou možnost než program ukončit.

Vznikne-li výjimka během new, handler zavolá delete a paměť se uvolní. Vznikne-li však vyjímka za new, delete se už nezavolá, leda že by výsledek funkce new byl uložen do nějakýho chytrýho pointeru, nebo objektu, který paměť uvolní při destrukci.

Pokud v konstruktoru alokujete paměť pomocí new a pak někdo hodí výjimku (v konstruktoru), musíte se připravit na to, že tuto výjimku je třeba zachytiti a paměť uvolnit, protože destruktor se nezavolá.

Já osobně dávám přednost řízenému oštření chyb.
1) Chyby během konstrukce objektu -> failstate objektu (objekt je platný, ale ve stavu fail, nepracuje)
2) Chyba během funkce -> návratová hodnota oznamující fail, nebo failobject
3) Chyba během funkce (jiná varianta) -> přepnutí objektu do stavu failstate (tohle dělá např. iostream).
4) Poslední dobou používám systém dopředných výjimek. Výjimku mohu hodit, ale nedochází ke stack unwind. Místo toho výjimku odchytí nějaké rozhraní, která může chybu zaznamenat do logu, zobrazit okénko, nebo odchytit jinak a nastavit se do failstate. Chyba se pak vrací z stejně jako v bodě 2) nebo 3) a teprve přesnou specifikaci chyby si přečte funkce z tohoto rozhraní a může na to nějak reagovat.
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 27.6.2006 09:02  476
Bredy [475]: Muzes trochu rozvest ten stack unwind? Prece i za normalnich okolnosti musi na konci funkce dojit k destrukci objektu na stacku, ne?
Jinak teda ja v C++ nikdy prakticky neprogramoval, z praktickeho pohledu znam jenom Javu a tam mi prijde, ze proste ty vyjimky jsou potreba. Ono kdyz se ten kod hemzi ruznymi vzdalenymi volanimi EJB nebo kdyz clovek pise nejaky nacitani konfigurace, kde proste muze dojit k IO chybam, k chybam parsovani XML, atd, atd, tak tam proste ty vyjimky patri a neni to tam jenom kvuli tomu, ze se muze taky slozit disk.
Samozrejme delat nejaky extremni try catch bloky neni asi vzdy to nejstastnejsi reseni, clovek by asi mel "trycatchovat" cilene. Na druhou stranu si dovedu predstavit to, ze clovek treba kazdej handler udalosti (clicknuti na tlacitko a podobne) celej hodi do jednoho velkyho try catch bloku (uvnitr kteryho ale dal cilene pouziva try catch na veci, kde je to potreba nebo kde je to vhodne), ve kterym uz odchyti opravdu kazdou vyjimku (tedy idealne nejake opravdu extremne necekane) a jako jeji osetreni vyhodi na uzivatele okno, ze doslo k neocekavane chybe, aplikaci je pri trose dobre vule mozno dale pouzivat, ale lepsi by bylo ji restartovat. Pri te prilezitosti hodi stacktrace plus cokoliv jineho zajimaveho nekam do logu.
bredy 27.6.2006 07:47  475
Johny_G: narazil hřebíček na hlavičku.

Z mýho pohledu jsou vyjímky opravdu nástrojem, který řeší skutečné havárie. Například že z nějakého neočekávaného důvodu dojde paměť, prostředky, složí se disk, nebo cokoliv. Výjimky ale bohužel lákají programátory chyby neošetřovat, ale prostě chybový blok ošetřit pomocí try catch a hledat chyby se nemusí.

Pokud mluvíme o výjimkách v C++, největším problémem je zde stack unwind. Kdo totiž programuje aplikace, které musí běžet nějak rychle, velice často používá stack jako paměť pro své objekty. A právě stack unwind je nějvětší problém, protože to znamená, že z každým objektem musí překladač do kódu zahrnout instrukce provádějící likvidace objektů na stacku. To o dost zdržuje.

No a v OOP výjimky nejsou proto, že objekty si posílají zprávy a volání funkce je vlastně zpráva s čekání na odpověď. Výjimka je vlastně takové násilné ukončení čekání.
johny_g Johny_G - Relaxační terapie pro lopušáky ZDARMA! 26.6.2006 19:09  474
Pokud vás zajímá i názor lamy, tak výjimky jsou výborné. Líbí se mi možnost zabránit kolapsu celého programu, aniž bych se musel zabývat původem chyby. IMHO je to veliká výhoda high-level programování, že si můžu jednotlivá místa programu ošetřit zcela univerzálně, aniž by mě rozhodila nějaká dosud neobjevená chyba ;-).
huh huh 26.6.2006 18:06  473
Výjimky jsou nejlepší vynález na světě. Bez nich je práce s chybami mnohonásobně větší opruz. Proč by se to mělo tlouct s OOP nechápu, výjimka je typicky nějaký objekt.
bredy 26.6.2006 16:53  472
Otázka. Používáte výjimky? A co si myslíte o výjimkách v C++. A obecně v OOP?

Můj pohled:
Výjimky se snažím nepoužívat, a do OOP nepatří.
bredy 22.6.2006 18:52  471
Problémem může být překladač, který zdrojový text čte v nějakém jiném kódování, než ty píšeš. Dopodučuju texty ukládat do resourců nebo externích souborů ve formátu UNICODE nebo UTF-8 (což ale znamená, že si je musíš převést)
anonym 22.6.2006 12:32  470
Mam problemy s UNICODE retezci pod win - pri pouziti foo(L"Nějaký textík") jde do foo text orezany o hacky a carky, jenom dlouhe i zustane. Co se musi kde zapnout, aby to neprekladal?

_UNICODE definovane mam, foo je "void foo(WHCAR* bar)".

bredy 11.6.2006 23:00  469
Čus.
Začal jsem psát seriál o OOP http://bredy.jinak.cz/?g=main&kat=21

Zatím je první díl v syrové formě, (ve které doufám postupně vychytám všechny pravopisné chyby :-)

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

(c) 2001-2011 Lopuch.cz   
Kontakt