reklama

C++ a výjimka v destruktoru

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #15 kdy: 05. 02. 2014, 12:30:00 »
To je teď nějaká móda, označovat kódy za "příliš sofistikované" a doporučovat psát hloupé kódy, které sice budou neefektivní, ale rozumí jim každý jouda? Já to vidím tak, že když se někdo, kdo nezná jazyk do hloubky, pokouší upravovat kód od člověka, který ten jazyk zná jako svoje boty, tak na tom nezřídka pohoří a pak začne trousit kydy o nepoužitelném kódu, místo aby si uvědomil, že nepoužitelný není ten kód, ale on. Místo úchylných požadavků, aby profesionálové psali jako začátečníci, by se spíš měl zavřít do knihovny a to co mu není jasné, se doučit.

Měl jsi někdy odpovědnost za nějaký projekt? Když budeš mít v týmu člověka, který píše nestandardně, povede to k horší kvalitě produktu, protože ostatní tomu kódu nerozumí / nechtějí rozumnět. Ve výsledku to dopadne tak, že se jeho kód nakonec musí vyhodit a napsat znovu normálně. Proto existují coding standards, aby všichni dodržovali nějakou kulturu a v kódu nebyly prasárny / špatně udržovatelné konstrukce. Znát jazyk jako svoje boty neznamená "můžu použít každou prasečinu, která v tom jde udělat".

reklama


JSH

Re:C++ a výjimka v destruktoru
« Odpověď #16 kdy: 05. 02. 2014, 12:36:16 »
Co třeba rezoluční funkci? ...
Spíš ignorační, ne? Už podle deklarace je jediným účelem téhle funkce se té nechtěné výjimky prostě nějak zbavit.

Takový návrh prostě narazí u té části lidí, kteří vyjímky chytají a neignorují. No a říct o lidech jako Stroustrup, Alexandrescu a podobných, že jsou to úředníci co neradi myslí ...  ::)
Citace
V případě výjimky destruktoru jde vlastně o uvedení objektu do původního stavu a jeho následnou destrukci, což vede k tomu, co jsem říkal a žádný logický rozpor tam není.
A ta vnořená destrukce házet může, nebo ne? Vždyť likviduje úplně to samé, jako ta vnější. Nebo se to, co se nepodaří zrušit, taky prostě odignoruje?
Citace
Jak? Co děláte, když vám ve standardním C funkce fclose() oznámí chybu? Zpravidla nic, zaignorujete to.
Když na tom nesejde, tak ano. Ale když na tom nesejde, tak můžu chyby odignorovat rovnou a nemusím nic házet.
Citace
To je validní řešení. Destruktor je něco jako konečné řešení. V destruktoru by se neměla dělat validace požadavku. Není problém volání metody Word::save() před jeho destrukcí. Nehledě na to, že je dost diskutabilní, jestli by destruktor objektu Word měl volat save. Nicméně destruktor nějakého bufferovaného streamu by měl zavolat flush() (viz dále)
Takže neuložení souboru je špatně, ale když neprojde flushnutí bufferu a díky tomu ten soubor nepůjde otevřít, tak je to něco jiného? Já v tom žádný principielní rozdíl nevidím. V obou případech je to nespolehlivé.
Kód: [Vybrat]
~WriteBuffer() {
try {
flush();
} catch (...) {
if (!std::uncaught_exception())
    throw;
}
}
Jak už jsem psal. Pokud šoupnu flush do destruktoru a budu na to spoléhat, tak program sem tam vyprodukuje binec. Pokud budu házet, tak některé případy chytnu ale některé stejně projdou. Pokud mi na tom nefičí, tak nemusím házet vůbec. Pokud mi na tom záleží, tak mi házení moc nepomůže.

Představte si, že je ten buffer použitý někde hluboko uvnitř knihovny. Už vidím tu dokumentaci: Pozor, během stack unwindingu někdy nedojde k zápisu celého souboru! :o
Kód: [Vybrat]
Transaction::~Transaction() {
try {
rollback();
} catch (...) {
//catch exception if we are in exception
if (!std::uncaught_exception()) throw;
}
}
Házející rollback? V jakém stavu je ta transakce, pokud rollback vyhodí chybu? Co v takovém případě vlastně můžu dělat? Na tomhle příkladě smrdí daleko víc, než jen házení z destruktoru.
Citace
Považujte mě za génia (minimálně za člověka, který 20 let programuje z toho 15 let v C++). Ale tvrdím, že standardní C++ knihovna byla napsána dementy pro dementy. Spoustu věcí v ní nejde, takže už jí několik let (bude to za chvíli přes 10) nepoužívám , maximálně tak okrajově.
Někoho kdo ignoruje to, že se STL musí vypořádat se spoustou protichůdných požadavků a díky tomu vypadá tak, jak vypadá? Nebojte, za génia Vás určitě považovat nebudu.

Re:C++ a výjimka v destruktoru
« Odpověď #17 kdy: 05. 02. 2014, 12:38:14 »
udržovatelné konstrukce. Znát jazyk jako svoje boty neznamená "můžu použít každou prasečinu, která v tom jde udělat".

To s tím nesouvisí. Standardní knihovny jsou plné prasečin. Jen si někdy projdi zdrojáky stl. Najdeš někoho, kdo by jim rozuměl? To je plné prasáckých konstrukcí!

 Základem úspěšného vedení týmu je dokumentace kódu. Není možné vést tým tak, že ho budu nutit psát tak, aby to bylo čitelné bez dokumentace. Dokumentace je základ. Minimálním nárokem je dokumentace rozhraní, kdy dokumentace plní také roli podrobné specifikace (pak je snadné rozhodnout, jestli odlišné chování programu je chyba nebo to tak autor skutečně zamýšlel).

djicha

Re:C++ a výjimka v destruktoru
« Odpověď #18 kdy: 05. 02. 2014, 12:50:04 »
Zdravím, celá ta diskuze odbočila jinam než byl původní dotaz. Ale i tak je to krásné téma.
Bereme li v úvahu průměrné složení týmu, kdy jsou leadery jeden až dva senioři a zbytek juniorů v různém stádiu zkušeností, je největším problémem u pře-designovaného kódu právě zastupitelnost oněch seniorů. Jde v první řadě o peníze, takže by chybu měli být schopní opravit v čase stanoveným nějakým SLA i méně zdatní nebo zkušení. Pokud si senior bude honit triko tím že bude psát pro ostatní nepochopitelný kód, což si zatím nikdo koho znám nedovolil, je zaděláno na problémy především jemu, protože nebude moci ani na dovolenou.
Dalším faktem téhle práce bezesporu zkutečnost, že zákazníka pokud jím není jiná programátorská firma konkrétní implementace nezajímá, dokud to není pomalé, nebo to ukazuje něco co nemá. U nepřehledného kódu hrozí "nevíme co to dělá, na to se nesahá" tak se nalepí nad to nějaká další vrstva bordelu, a složitůra udržovatelnosti exponenciálně vzroste. Nesmí se prostě stát, že se řekne, to je šéfova funkce, bojím se ji opravit.
Navíc sebe vybavenější knihovna nenahradí opravdovou práci.
Ono bohatě stačí když se používá jiná logika u ternárního operátoru
Object o = i == null ? null : 1; nebo
Object o = i != null ? 1 : null;, význam je stejný, ale čitelnost a srozumitelnost se na první pohled velmi liší.
Je to konvencích a pokud se je naučí používat i junioři nebudou pak mít problém pochopit to co napsal senior.

Co se týče dokumentace, je dle mého názoru lepší když je kód dokumentovaný už tím jak je napsaný, ona dokumentace jakého koliv charakteru nemá šanci na dlouhodobé přežití.

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #19 kdy: 05. 02. 2014, 12:54:34 »
To s tím nesouvisí. Standardní knihovny jsou plné prasečin. Jen si někdy projdi zdrojáky stl. Najdeš někoho, kdo by jim rozuměl? To je plné prasáckých konstrukcí!
Občas zdrojáky STL čtu a dá se to pochopit. Samozřejmě, že to není psané úplně čitelně, ale to má dobrý důvod. Třeba normální názvy proměnných si autoři nemůžou dovolit kvůli preprocesoru.

Rozhranní STL (s přihlédnutím ke kompatibilitě a podobným věcem) je velice elegantní. Samozřejmě, že se najdou diskutabilní místa, ale celkově je tam těch prasečin docela málo.

reklama


aaa

Re:C++ a výjimka v destruktoru
« Odpověď #20 kdy: 05. 02. 2014, 12:57:04 »
void on_double_exception()  throw();

Pokud by nastala dvojitá vyjímka, program by ihned skočil do této funkce, s tím, že by to bylo součástí nějakého univerzální catch handleru před tím, než by se pokračovalo v unwindingu původní výjimky
Proc to zastavovat u druhe vyjimky? Co kdyz nastane k-ta vyjimka? Zavedme si funkci on_kth_exception(int k)!

A vazne - ohackovavat v jazyku neco, co programator nezvladne osetrit sam, to je cesta do pekel.

Výjimka má za úkol přerušit další běh programu a nasměrovat ho k nejbližšímu exception handleru a předat mu chybový objekt.
A co udela ten exception handler? Proc se nemuze vyjimka zachytit v destruktoru a rovnou obslouzit?

Jak? Co děláte, když vám ve standardním C funkce fclose() oznámí chybu? Zpravidla nic, zaignorujete to.
Proc se tedy snazite neignorovat chybu (vyjimku) v destruktoru, ale vymyslite nezmysly, jak je chytat?

Kód: [Vybrat]
~WriteBuffer() {
try {
flush();
} catch (...) {
if (!std::uncaught_exception())
    throw;
}
}


Kód: [Vybrat]
Transaction::~Transaction() {
try {
rollback();
} catch (...) {
//catch exception if we are in exception
if (!std::uncaught_exception()) throw;
}
}
(ukázky z mého kódu)
A co kdyz se to nepovede? Co s vyjimkou? Ignorujete ji? Nac pak delate rethrow?

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #21 kdy: 05. 02. 2014, 12:58:59 »
Jak řešit vyhození výjimky při unwindingu jiné? Potichu ignorovat původní, nebo novou výjimku? Nebo je nějak poskládat?

Ignorovat novou výjimku, protože je pravděpodobně zanesená. Ten objekt se totiž v tu chvíli destruuje kvůli té původní výjimce.

Pokud ale chcete být opravdu přesný, tak byste asi použil std::current_exception() a přidal do vyhozené výjimky tuhle další.

Vyhozená výjimka znamená, že se operace neprovedla a objekt by měl být v nějakém konzistentním stavu. Ideálně tak, jak byl před začátkem té chybné operace aby se dala třeba zopakovat. Akorát že v destruktoru je to naprosto nechtěné chování. Takže pro destruktor se musí napsat úplně znova všechno, co zavání rollbackem(v rámci toho rušeného objektu), protože ty operace místo návratu musí pokračovat v likvidování. To znamená, že ten házející destruktor musí pro případ, že by vyhodil výjimku obsahovat i nějaký kompletní úklid. Nepodobá se to tak trochu neházejícímu destruktoru?

Smazání objektu bez memory leaku je také konzistentní stav. Po vyhození výjimky z destruktoru se samozřejmě dostanete před začátek té chybné operace, ta totiž spočívá ve všem od konstruktoru toho objektu až po jeho destruktor.

A co se dá dělat v případě, že destruktor vyhodí výjimku? Objekt už neexistuje, takže se z toho nedá nijak vzpamatovat. Musí se kompletně zopakovat celá operace, jejíž závěr (třeba zápis patičky nějakého souboru) takhle selhal. Pokud ten házející závěr vyhodím do vlastní metody, tak pokud vyhodí výjimku, tak ji můžu chytnout ještě před zlikvidováním objektu a možná to půjde nějak zachránit. Házející destruktor sice zahlásí chybu, ale všechno zlikviduje jako by se nechumelilo. Něco jako by word při vypínání zahlásil, že se soubor nepodařilo uložit, ale dokument by stejně zavřel.

A co se udělá v případě, kdy ten destruktor tu výjimku nevyhodí? Něco jako kdyby se Wordu při vypínání nepodařilo souboru uložit a ani to neohlásil. Jinak ukládání dat v destruktoru bych používal jen výjimečně a pokud to má smysl (např. pro memory-cached objekty, ale rozhodně ne pro dokumenty, u kterých není jasné, jestli to uživatel ukládat chce nebo ne).

Máte nějaký příklad, kdy je házení z destruktorů rozumné řešení? Já jsem se bohužel s takovým ještě nesetkal. Ve všech případech, kdy jsem měl chuť házet z destruktoru, to bylo jen mojí leností a pokud jsem si líp promyslel chybové situace, tak mi ty házející kousky kódu vybublaly z destruktorů ven.

Vzhledem k tomu, že C++ nemá finally, je těch případů docela dost. Vlastně všechny, kdy byste v Javě použil finally.

To s tím nesouvisí. Standardní knihovny jsou plné prasečin. Jen si někdy projdi zdrojáky stl. Najdeš někoho, kdo by jim rozuměl? To je plné prasáckých konstrukcí!

Které STL? ;) Třeba GNU ISO C++ library mi přijde docela srozumitelná.

Co se týče dokumentace, je dle mého názoru lepší když je kód dokumentovaný už tím jak je napsaný, ona dokumentace jakého koliv charakteru nemá šanci na dlouhodobé přežití.

Proto existuje Doxygen :)

Re:C++ a výjimka v destruktoru
« Odpověď #22 kdy: 05. 02. 2014, 13:10:40 »
Spíš ignorační, ne? Už podle deklarace je jediným účelem téhle funkce se té nechtěné výjimky prostě nějak zbavit.

Takový návrh prostě narazí u té části lidí, kteří vyjímky chytají a neignorují.
a jak to dělají, když v destruktoru vyhodit výjimku nesmějí. Jak jinak to dělají. Jediný co můžete s takovou výjimkou udělat je, že jí vyhodíte, nebo zaignorujete.

No a říct o lidech jako Stroustrup, Alexandrescu a podobných, že jsou to úředníci co neradi myslí ...  ::)

Jsou to lidé. Ne bohové. Alexandrescu má spoustu nápadů a některé práce jsem od něj četl a považoval jsem je za skvělé. Jindy mi to přišlo jako blbost a úchylárna. Třeba například jeho alokátor malých objektů byl bezva. Nicméně časem jsem ho vylepšil a začal používat jinak, protože pro jeho globalní řešení jsem nenašel uplatnění.

 Stroustrup.... no prostě to je člověk, který programuje úplně jinak než já. Co jsem od něj četl, to byla většinou pěkná prasárna. Tak jsem ho začal ignorovat. Tím ho nechci schazovat, jen mi úplně jeho styl nesedl


A ta vnořená destrukce házet může, nebo ne? Vždyť likviduje úplně to samé, jako ta vnější. Nebo se to, co se nepodaří zrušit, taky prostě odignoruje?
Napadáte příměr. Říkal jsem, že to lze chápat jako uvedení objektu do původního stavu a jeho následující destrukci. Nebo to berte tak, že to je uvedení objektu do stavu, kdy ho lze bezpečně a bez výjimek zdesrtruovat.

Když na tom nesejde, tak ano. Ale když na tom nesejde, tak můžu chyby odignorovat rovnou a nemusím nic házet.
A jak to uvnitř objektu poznáte, že na tom nesejde? A co když na tom sejde? Samozřejmě, že ve wraperu kolem FILE mám mojí oblíbenou konstrukci se std::uncaught_exception(). Nehledě na to, že ten wrapperu už stejně delší dobu nepoužívám.


Takže neuložení souboru je špatně, ale když neprojde flushnutí bufferu a díky tomu ten soubor nepůjde otevřít, tak je to něco jiného? Já v tom žádný principielní rozdíl nevidím. V obou případech je to nespolehlivé.

Záleží, jaké máte zadání. Jak se to bude používat. Pokud píšu objekt řešící streamování, tak nejspíš chci ukrýt nějaké vnitřní bufferování, které má za úkol, že mi optimalizuje zápis. V normální použití mi přijde naprosto nepřijatelné, abych se staral o flushování dat. Někde na to zapomenu a nastane problém. Prostě se streamem se pracuje tak, že buffer je vnitřní záležitost, která se nepřenáší ven. A pokud stream má funkcí flush(), tak se to většinou chápe jako hint (funkce může být prázdná).

U objektu Word který obsahuje dokument je věc odlišná. Dokument je věc veřejná o které se navenek ví. Je dokonce zadané, že ne vždy je uložení objektu chtěné - zatímco u streamu se předpokládá, že nabufferovaná data se vždy uloží,  u dokomentu ve wordu to není automatický předpoklad.

A mohl bych pokračovat dál, třeba u transakce se nepředpokládá, že by se automaticky commitovala. To nikdo zpravidla nechce, protože od toho transakce jsou. Člověk je chápe jako sandbox, do kterého si připraví všechny operace a až když to má, tak to commitne. Objekt Word lze stejně podobně chápat. Je to spíš sandbox, než stream.

Dobrý programátor si umí udělat analýzu problému a hned vidí, co je a co není logické a jak by to měl používat. Špatný programátor klade takovéhle otázky, aniž by se nad tím zamyslel.

Jak už jsem psal. Pokud šoupnu flush do destruktoru a budu na to spoléhat, tak program sem tam vyprodukuje binec. Pokud budu házet, tak některé případy chytnu ale některé stejně projdou. Pokud mi na tom nefičí, tak nemusím házet vůbec. Pokud mi na tom záleží, tak mi házení moc nepomůže.

Jestli vám některé případy stejně projdou, tak byste se měl hluboce zamyslet nad tím, k čemu používáte výjimky. Možná je nepoužíváte správně. Výjimky řeší výjimečné situace, zpravidla situace, kdy se operace nezdaří. Program se většinou píše tak, že se předpokládá, že všechny operace se zdaří.  A pokud je chyba správnou operací, pak se neřeší výjimkou. Takže špatný předpoklad. Ten flush se provede vždy. Když se provádí uvnitř výjimky a nezdaří se, tak se tedy zaignoruje, protože je vysoká pravděpodobnost, že jde o zavlečenou chybu, tedy že to nezdaření je stejně důsledkem již probíhající výjimky. Vaše "někdy stejně projdou" je akademická diskuze a spíš ukazuje na hluboké nepochopení problematiky.

Představte si, že je ten buffer použitý někde hluboko uvnitř knihovny. Už vidím tu dokumentaci: Pozor, během stack unwindingu někdy nedojde k zápisu celého souboru! :o

nic takového tam samozřejmě nebude. Viz výše. Výjimky se nesmí používat k normálnímu běhu kódu.


Házející rollback? V jakém stavu je ta transakce, pokud rollback vyhodí chybu? Co v takovém případě vlastně můžu dělat? Na tomhle příkladě smrdí daleko víc, než jen házení z destruktoru.

Představte si kod:
Kód: [Vybrat]
{
  {
   Transaction trn1(connection);
   trn1.neco();
   }
  {
   Transaction trn2(connection);
   trn2.neco();
   }
}
Pokud vylítne výjimka v destruktoru první transakce, tedy rollback vyhodil výjimku, něco nepěkného se nejspíš stalo se spojením s databází. Pak je dobré ukončit tento blok, než se snažit pokračovat vytvářením druhé transakce. Navíc chybová hláška z první výjimky bude asi znít "connection lost", zatímco druhá výjimka, která velmi pravděpodobně vypadne při vytvoření druhé transakce už může znít "invalid socket". Vyhození výjimky při rollbacku je tedy lepší a bezpečnější řešení.

Nikdy jste neprogramoval databáze? Že se divíte rollbacku házící výjimku.


Někoho kdo ignoruje to, že se STL musí vypořádat se spoustou protichůdných požadavků a díky tomu vypadá tak, jak vypadá? Nebojte, za génia Vás určitě považovat nebudu.
Já jsem neříkal, že jí ignoruju, já jsem říkal, že jí nepoužívám. Jak bych mohl, když mé objekty háží v destruktoru výjimky, nebo když používam custom alokátory (které STL neumí - i když vám kdejaký jouda bude tvrdit, že ano). Používám vlastní streamy (zkuste někdy napsat vlastní verzi std::iostream.... dlouhe zimní večery už jsou minulostí). Takže neignoruju, jen nepoužívám. V mých knihovnách není problém STL používat, ale zpravidla se ukáže, že je to k ničemu.

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #23 kdy: 05. 02. 2014, 13:15:09 »
Vzhledem k tomu, že C++ nemá finally, je těch případů docela dost. Vlastně všechny, kdy byste v Javě použil finally.
Ono to házení z finally v Javě má taky svůj příděl problémů. Jestli se nepletu, tak ta nová výjimka potichu přeplácne tu starou, ale tady si jistý nejsem.

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #24 kdy: 05. 02. 2014, 13:28:54 »
Já jsem neříkal, že jí ignoruju, já jsem říkal, že jí nepoužívám. Jak bych mohl, když mé objekty háží v destruktoru výjimky, nebo když používam custom alokátory (které STL neumí - i když vám kdejaký jouda bude tvrdit, že ano). Používám vlastní streamy (zkuste někdy napsat vlastní verzi std::iostream.... dlouhe zimní večery už jsou minulostí). Takže neignoruju, jen nepoužívám. V mých knihovnách není problém STL používat, ale zpravidla se ukáže, že je to k ničemu.

Opravdu to stojí za to? Přináší vyhazování výjimek v destruktoru, psaní custom STL nekompatibilních alokátorů, vlastních streamů a obecně nepoužívání STL takové benefity, že se to vyplatí? Budou takový kód ostatní programátoři rádi studovat a udržovat? Bude to stejně prověřené a odladěné jak STL, které používají miliony uživatelů?

Re:C++ a výjimka v destruktoru
« Odpověď #25 kdy: 05. 02. 2014, 13:34:40 »
void on_double_exception()  throw();
Proc to zastavovat u druhe vyjimky? Co kdyz nastane k-ta vyjimka? Zavedme si funkci on_kth_exception(int k)!
Ve kterém bodě by nastala k-ta výjimka. Podívejte se na tu definici znova. Vidíte throw()?

Definice měla být takováto. Pokud při zavolání destruktoru během stack unwind dojde k výjimce, zavolá se funkce on_double_exception s tím, že current exception bude ta, která byla vyhozena. Funkce on_double_exception() bude považován za handler, takže throw; způsobí nové výhození aktuální výjimky. Pokud funkce skončí, bude výjimka považovaná za vyřešenou a program se vrátí k původnímu stack unwind. Pokud však funkce skončí s výjimkou, pak už asi nezbývá jiné řešení, než terminate. Protože tahle funkce by měla řešit double exception. Kde by nastala třetí exception? Pokud v té funkci, tak si jí musí ošetřit sama. Pokud při stack unwindingu v rámci té funkce, tak se to musí pořešit rekuzivním voláním téže funkce. Klidně to může jít do nekonečna, až dojde zásobník (v krajním případě)

Opravdu to stojí za to? Přináší vyhazování výjimek v destruktoru, psaní custom STL nekompatibilních alokátorů, vlastních streamů a obecně nepoužívání STL takové benefity, že se to vyplatí? Budou takový kód ostatní programátoři rádi studovat a udržovat? Bude to stejně prověřené a odladěné jak STL, které používají miliony uživatelů?

Samozřejmě přináší. Zpravidla výkon. Nezanedbatelné zrychlení. Dělal jsemi nějaké benchmarky. Používá se to stejně snadno jako STL, tedy pokud si to někdo nastuduje s přiložené dokumentace. Chystám se knihovnu udělat open-source, ale to vyžaduje práci navíc (vyházení obsolete věcí a revizi dokumentace) a momentálně na to nemám čas.

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #26 kdy: 05. 02. 2014, 13:49:55 »
Samozřejmě přináší. Zpravidla výkon. Nezanedbatelné zrychlení. Dělal jsemi nějaké benchmarky. Používá se to stejně snadno jako STL, tedy pokud si to někdo nastuduje s přiložené dokumentace. Chystám se knihovnu udělat open-source, ale to vyžaduje práci navíc (vyházení obsolete věcí a revizi dokumentace) a momentálně na to nemám čas.

Premature optimization is the root of all evil:
http://c2.com/cgi/wiki?PrematureOptimization
Moje zkušenost je taková, že pokud bylo něco příliš pomalé, tak to bylo chybně zvoleným algoritmem a bylo to stejně nutné celé předělat. K apriori optimalizacím jako vrazit tam pro jistotu jiný alokátor nebo custom stream jsem skeptický.

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #27 kdy: 05. 02. 2014, 13:59:07 »
Vzhledem k tomu, že C++ nemá finally, je těch případů docela dost. Vlastně všechny, kdy byste v Javě použil finally.
Ono to házení z finally v Javě má taky svůj příděl problémů. Jestli se nepletu, tak ta nová výjimka potichu přeplácne tu starou, ale tady si jistý nejsem.

Jj, je to tak. Ale jednou se to dostalo do standardu, tak už se nedá nic dělat. Asi i proto se ISO C++ snaží vyhnout výjimkám v destruktorech.

Premature optimization is the root of all evil:
http://c2.com/cgi/wiki?PrematureOptimization
Moje zkušenost je taková, že pokud bylo něco příliš pomalé, tak to bylo chybně zvoleným algoritmem a bylo to stejně nutné celé předělat. K apriori optimalizacím jako vrazit tam pro jistotu jiný alokátor nebo custom stream jsem skeptický.

To jste asi ještě nečetl porovnání výkonu iostream a fread :)

Re:C++ a výjimka v destruktoru
« Odpověď #28 kdy: 05. 02. 2014, 14:01:09 »
Premature optimization is the root of all evil:
http://c2.com/cgi/wiki?PrematureOptimization
Moje zkušenost je taková, že pokud bylo něco příliš pomalé, tak to bylo chybně zvoleným algoritmem a bylo to stejně nutné celé předělat. K apriori optimalizacím jako vrazit tam pro jistotu jiný alokátor nebo custom stream jsem skeptický.

Akademické půdě je jedno, jestli algoritmus trvá 10 sekund nebo 100 sekund, důležité je, že má složitost N a ne N^2. Zákazníkovi to zpravidla ale vadí, a pokud dokážete svůj kód zrychlit desetkrát... budou vám líbat ruce.

... a to jenom proto, že jste místo std::string použili můj LightSpeed::ConstStrA.

Na akademické půdě lze připustit, že v praktickém nasazené lze kód optimalizovat. V bysnysu ale na to zpravidla nejsou čas ani peníze.

Navíc problém STL je ten, že Vás (a Váš kód) zdrže svými svazujícími pravidly (například nemožnost strkat do kontejnerů objekty bez povolené operace přiřazení, nebo s výjimkami v destruktorech) jenom proto, aby to bylo spíš akademické, než praktické. Takže možná tak na výuku programování. V bysnysu... ne. Ono to končí zpravidla tím, že programátor začne stl obcházet a hackovat (viděno na vlastní oči, ač si to většinou autoři neuvědomují... považují to za součást stylu)

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #29 kdy: 05. 02. 2014, 14:04:09 »
a jak to dělají, když v destruktoru vyhodit výjimku nesmějí. Jak jinak to dělají. Jediný co můžete s takovou výjimkou udělat je, že jí vyhodíte, nebo zaignorujete.
A co takhle dát to jinam, než do destruktoru. Pokud tu výjimku nemůžu ignorovat, tak to nesmí být v destruktoru, protože tam se o ní občas nedovím ať dělám, co dělám.
Citace
Jsou to lidé. Ne bohové...
Ale už to nejsou úředníci, co neradi myslí, co?  ;)
Citace
Stroustrup ... Tak jsem ho začal ignorovat. Tím ho nechci schazovat, jen mi úplně jeho styl nesedl
A tohle si návrháři C++ prostě dovolit nemůžou. Prostě nemůžou některé požedavky prostě ignorovat.
Citace
Napadáte příměr. Říkal jsem, že to lze chápat jako uvedení objektu do původního stavu a jeho následující destrukci. Nebo to berte tak, že to je uvedení objektu do stavu, kdy ho lze bezpečně a bez výjimek zdesrtruovat.
A ten důvod, proč to předtím bezpečně a bez výjimek zdestruovat nešlo, zmizí jak?
Citace
A jak to uvnitř objektu poznáte, že na tom nesejde? A co když na tom sejde?
To samozřejmě poznám už ve chvíli, kdy ten kód píšu. Pokud na tom sejde, tak si nemůžu dovolit ani
Kód: [Vybrat]
if(uncaught_exception())
  nejak_se_te_chyby_zbav_at_neprudi()
Zalogování chyby je pro vývojáře a ne pro uživatele.
Citace
Jestli vám některé případy stejně projdou, tak byste se měl hluboce zamyslet nad tím, k čemu používáte výjimky.
Já ale psal, že VÁM některé výjimky projdou. Já se s nimi vypořádávám tak, že do destruktoru necpu to, co tam není třeba. Díky tomu nemusím testovat, jestlivýjimku hodit nebo ignorovat, jak to děláte vy.
Pokud je mi při úklidu jedno, jestli flush skončil s chybou nebo ne, pak je mi i jedno jestli vůbec proběhl.
Citace
Výjimky se nesmí používat k normálnímu běhu kódu.
To jsem ani nikde nepsal. Já psal o případu, že se někdo jako vy pokusí v destruktoru uložit při chybě soubor pomocí vaší knihovny. V téhle chvíli se vaše knihovna s vaším bufferem bude tvářit jako že je všechno ok, i když uloží neúplný soubor.
Citace
Já jsem neříkal, že jí ignoruju, já jsem říkal, že jí nepoužívám.
Ani já nepsal, že ignorujete STL. Já říkal, že ignorujete všechny požadavky na ni, které nepotřebujete vy sám a díky tomu jste ji shrnul jako od blbců pro blbce.
Citace
...nebo když používam custom alokátory (které STL neumí - i když vám kdejaký jouda bude tvrdit, že ano).
Neumí to STL, nebo Novák?  :P

 

reklama