C++ a výjimka v destruktoru

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #30 kdy: 05. 02. 2014, 14:06:10 »
To jste asi ještě nečetl porovnání výkonu iostream a fread :)

Ale jo četl, nicméně pokud se v performance critical kódu používají streamy, tak je něco v principu špatně, protože jsou opravdu pomalé.
Mimochodem pokusů udělat lepší (rychlejší, přenositelnější...) implementaci STL už bylo hodně a nikdy nevzniklo nic světoborného, nejlíp z toho asi vyšel  STLport:
http://stlport.sourceforge.net/FAQ.shtml



gamer

Re:C++ a výjimka v destruktoru
« Odpověď #31 kdy: 05. 02. 2014, 14:11:13 »
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)

Aha, takže až vydáte tu Vaši knihovnu, tak celý business zahodí STL a začně to používat, protože všichni pojídači koláčů, kteří se někde na akademické půdě naučili STL, budou mít konečně mnohem rychlejší a použitelnějsí standardní knihovnu do C++ :).

Re:C++ a výjimka v destruktoru
« Odpověď #32 kdy: 05. 02. 2014, 14:15:25 »
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.
Když to začnete řešit takhle, narušujete koncept RAII. Protože vyžadujete explicitní uzavření prostředku, což je proti duchu RAII. Co když na to zapomenete?

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
A co když píšete knihovní objekt? Kde to jestli na tom sejde nebo nesejde záleží na tom, kdo to bude používat? A co když přitom nechcete narušit koncept RAII? Napíšete do dokumentace: "Vždycky na konci bloku zavolat JHS.close(), jinak vám to nebude fungovat". Už vidím tuny kódu, kde na to lidi zapomenou.
[/quote]
Zalogování chyby je pro vývojáře a ne pro uživatele.
Co třeba logovat chyby pro helpdesk?

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.
A to jenom pokud to selže výjimkou. Ten způsob řeší opravdu jen situaci, kdy něco selže dvakrát za sebou. Nebo mi napište, jak byste to řešil vaším explicitním zavíráním, kdy nemůžete v destruktoru vyhodit výjimku. Co když tedy ten flush selže? Co dál?

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
To je právě to, STL custom alokátory jsou velmi nepraktické a nepoužitelné. Bohužel jsou součástí  standardu.

Aha, takže až vydáte tu Vaši knihovnu, tak celý business zahodí STL a začně to používat, protože všichni pojídači koláčů, kteří se někde na akademické půdě naučili STL, budou mít konečně mnohem rychlejší a použitelnějsí standardní knihovnu do C++ :).

troll alert

lulik

Re:C++ a výjimka v destruktoru
« Odpověď #33 kdy: 05. 02. 2014, 14:23:31 »
Ondrej Novak - to je ten programator s patnactiletou praxi, co pise derave webove aplikace, nema zakladni prehled o kryptografii a chtel by vytvorit skvele zabezpecenou pevnost pro obchodovani s kryptomenou?

hmm, od nej bych si dal rict :)

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #34 kdy: 05. 02. 2014, 14:33:00 »
Napíšete do dokumentace: "Vždycky na konci bloku zavolat JHS.close(), jinak vám to nebude fungovat".
Vaše řešení zase o tolik lepší není. "Destruktor se pokusí flushnout buffer. Pokud se mu to nepodaří, tak možná vyhodí výjimku."
Nezapomínejte, že váš kód se může volat z místa kde není úplně jasné, jestli se to právě vykonává při úklidu, nebo při normálním průběhu.
Citace
Nebo mi napište, jak byste to řešil vaším explicitním zavíráním, kdy nemůžete v destruktoru vyhodit výjimku. Co když tedy ten flush selže? Co dál?
A co takhle si na nic nehrát a do dokumentace to napsat? "Destruktor se pokusí flushnout buffer, ale může to selhat. Pokud je to důležité, flushněte ho ručně předem."


Sten

Re:C++ a výjimka v destruktoru
« Odpověď #35 kdy: 05. 02. 2014, 14:38:27 »
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.

Proč to dělat jednoduše, když to jde složitě, že. Nakonec takové goto má taky svoje kouzlo, kdo potřebuje nějaké destruktory :)

A ten důvod, proč to předtím bezpečně a bez výjimek zdestruovat nešlo, zmizí jak?

Nijak nezmizí. Zásadní rozdíl je v tom, že teď výjimka vyletí, zatímco předtím se to tiše ignorovalo.

Vaše řešení zase o tolik lepší není. "Destruktor se pokusí flushnout buffer. Pokud se mu to nepodaří, tak možná vyhodí výjimku."
Nezapomínejte, že váš kód se může volat z místa kde není úplně jasné, jestli se to právě vykonává při úklidu, nebo při normálním průběhu.

Tak to je asi std::uncaught_exception náhodný generátor.

Re:C++ a výjimka v destruktoru
« Odpověď #36 kdy: 05. 02. 2014, 14:41:11 »
Napíšete do dokumentace: "Vždycky na konci bloku zavolat JHS.close(), jinak vám to nebude fungovat".
Vaše řešení zase o tolik lepší není. "Destruktor se pokusí flushnout buffer. Pokud se mu to nepodaří, tak možná vyhodí výjimku."
Nezapomínejte, že váš kód se může volat z místa kde není úplně jasné, jestli se to právě vykonává při úklidu, nebo při normálním průběhu.
Citace
Nebo mi napište, jak byste to řešil vaším explicitním zavíráním, kdy nemůžete v destruktoru vyhodit výjimku. Co když tedy ten flush selže? Co dál?
A co takhle si na nic nehrát a do dokumentace to napsat? "Destruktor se pokusí flushnout buffer, ale může to selhat. Pokud je to důležité, flushněte ho ručně předem."

Není to to samé. Já nevkládám povinnost na bedra programátora. Destruktor se snaží vyřešit výjimečnou situací in best-effort. Což je lepší, než se na to vykašlat a spoléhat na programátora, že to udělá sám. Ani mé řešení nevylučuje si ten flush zavolat ručně, pokud je to důležité. Cílem však je, aby tam, kde to není potřeba se to neřešilo.

(ona ten váš explicitní flush totiž vyžaduje, aby se to řešilo i v situaci, kdy k žádné chybě nedošlo, zatímco řešení destruktorem to vyžaduje jen v situacích, kdy takové nebezpečí hrozí. Za mé praxe jsem se setkal jen s jedním případem, kdy se uncaught_exception nedalo použit, protože zrovna byla true. Ale to byl speciální případ a navíc nakonec i špatný návrh). Pořád si myslím, že mé řešení je pro programátora mnohem příjemnější i za cenu toho, že ve velmi speciální a zpravidla chybových stavech se prostě ty data neflushnou.

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #37 kdy: 05. 02. 2014, 14:44:40 »
Ale jo četl, nicméně pokud se v performance critical kódu používají streamy, tak je něco v principu špatně, protože jsou opravdu pomalé.

Pěkné, důkaz kruhem v jedné větě :)

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #38 kdy: 05. 02. 2014, 14:53:50 »
Tak to je asi std::uncaught_exception náhodný generátor.
Není to náhodný generátor. Jen občas vrací true i když by výjimky šly úplně normálně házet. uncaught_exception neřeší, jak hluboko jsme od toho destruktoru, ze kterého ta výjimka nesmí vyletět. Díky tomu prostě nemůžu ve svém kódu spoléhat na to, že když nevyletěla výjimka, tak mi v tom destruktoru flush prošel. Můžu leda tak v dokumentaci zakázat, aby můj kód někdo volal z destruktoru.

Prostě destruktory, které chyby zásadně nehlásí mi přijdou bezpečnější než ty, které je obvykle hlásí. Stejně se na to spolehnout nemůžu a aspoň nemám iluzi bezpečí.

Re:C++ a výjimka v destruktoru
« Odpověď #39 kdy: 05. 02. 2014, 15:06:01 »
Díky tomu prostě nemůžu ve svém kódu spoléhat na to, že když nevyletěla výjimka, tak mi v tom destruktoru flush prošel. Můžu leda tak v dokumentaci zakázat, aby můj kód někdo volal z destruktoru.

Samozřejmě že:
Kód: [Vybrat]
U::~U {
      BufferedFile f("ahoj.txt");
      f << "nazdar";
}

může při výjimce způsobit prázdný soubor. Vyřeším to tím, že tam strčím explicitně f.flush(). Ve vašem případě by byl povinný. Ale je otázkou, jestli tohle vůbec je vhodné místo v destruktoru dělat. Jestli to vůbec svědčí o správném návrhu.

Re:C++ a výjimka v destruktoru
« Odpověď #40 kdy: 05. 02. 2014, 15:07:02 »
....

Zapoměl jsem dodat... za předpokladu, že ten flush selže... Protože jinak to funguje jak má. Proto slovo "může".

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #41 kdy: 05. 02. 2014, 15:09:22 »
Pěkné, důkaz kruhem v jedné větě :)

Asi takhle, když zjistím, že jsou streamy přiliš pomalé, mám dvě možnosti:
1) Místo streamů použít něco jiného rychlejšího (stdio)
2) Napsat si vlastní rychlejší streamy
Já považuju za lepší variantu 1, pan Novák 2. Psát vlastní streamy nechci, protože se duplikuje funkcionalita STL streamů a vznikne hodně nového kódu, který se musí udržovat, což stojí čas a peníze. Navíc to zrychlení je vždycky za nějakou cenu (autoři STL nejsou úplně hloupí a nepíšou záměrně pomalý kód). Takových pokusů udělat něco rychleji nebo lépe než STL už byla celá řada a i když vznikly dobré věci (třeba loki library), mají omezené použití (lidi to neznají nebo tomu nevěří, protože to není dost používané, nebo si nechtějí do projektu zatahovat další kód).

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #42 kdy: 05. 02. 2014, 15:11:08 »
Ve vašem případě by byl povinný. Ale je otázkou, jestli tohle vůbec je vhodné místo v destruktoru dělat. Jestli to vůbec svědčí o správném návrhu.
Já nemám nic proti tomu, zkusit v tom destruktoru ten buffer flushnout. Podle mě jen nemá cenu tu výjimku házet, protože se na to stejně nedá spolehnout.

Re:C++ a výjimka v destruktoru
« Odpověď #43 kdy: 05. 02. 2014, 15:15:15 »

Pan Novák samozřejmě udělal 1. Když už to dělal asi po třetí, napadlo ho, že by si na to mohl udělat přípravek. Z přípravku vznikla nová knihovna pro rychlejší streamy. A protože byly nejen rychlé, ale časem si na ně pan Novák zvyknul, přizpůsobil zbytek programu těmto novým streamům a začal je používat všude. Už proto, že na ně převedl veškerou komunikaci po síti nebo třeba roury a podobně. Dokonce má i http stream.

Nicméně ještě před bodem 1 bych přidal jeden marný pokus napsat vlastní implementaci iostreamu ... ale dědit něco z STL se prostě nedá.

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #44 kdy: 05. 02. 2014, 15:19:45 »
Není to náhodný generátor. Jen občas vrací true i když by výjimky šly úplně normálně házet. uncaught_exception neřeší, jak hluboko jsme od toho destruktoru, ze kterého ta výjimka nesmí vyletět. Díky tomu prostě nemůžu ve svém kódu spoléhat na to, že když nevyletěla výjimka, tak mi v tom destruktoru flush prošel. Můžu leda tak v dokumentaci zakázat, aby můj kód někdo volal z destruktoru.

Nějak nechápu, proč by měl ve chvíli, kdy se hledá handler pro mnohem vážnější výjimku, mělo zajímat, jestli prošel flush, když nadřazený objekt je stejně rozhozený.

Asi takhle, když zjistím, že jsou streamy přiliš pomalé, mám dvě možnosti:
1) Místo streamů použít něco jiného rychlejšího (stdio)
2) Napsat si vlastní rychlejší streamy
Já považuju za lepší variantu 1, pan Novák 2. Psát vlastní streamy nechci, protože se duplikuje funkcionalita STL streamů a vznikne hodně nového kódu, který se musí udržovat, což stojí čas a peníze. Navíc to zrychlení je vždycky za nějakou cenu (autoři STL nejsou úplně hloupí a nepíšou záměrně pomalý kód). Takových pokusů udělat něco rychleji nebo lépe než STL už byla celá řada a i když vznikly dobré věci (třeba loki library), mají omezené použití (lidi to neznají nebo tomu nevěří, protože to není dost používané, nebo si nechtějí do projektu zatahovat další kód).

Samozřejmě, námaha by měla odpovídat efektu. Nicméně stdio není ekvivalentní streamům, neumí RAII. A když k tomu napíšete RAII obal, velmi rychle zjistíte, že vlastně začínáte psát vlastní streamy :)