C++ a výjimka v destruktoru

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #75 kdy: 06. 02. 2014, 08:58:14 »
Já ty chyby ale neignoruji ;)
To já ne, to ten destruktor? Zastávám názor, že házení výjimek jen pokud to ničemu nevadí není řešení.

Zdůvodním :
1) Pokud mi destruktory neházejí, vím, že se o chybách uvnitř destruktorů nedovím. Pokud se chci spolehnout, že všechno klaplo, musím to před zrušením objektu zkontrolovat.
2) Pokud mi destruktory házejí, tak vím že se o chybách občas taky nedovím. Pokud se chci spolehnout, že všechno klaplo, tak to musím taky zkontrolovat před zrušením objektu. A navíc musím samozřejmě chytat ty výjimky, takže místo jednoho místa ošetřuju stejnou chybu na dvou místech. A to se prostě vyplatí.

Samozřejmě že můžu zapojit svou kreativitu a říct si že ty výjimky které se mi nelíbí jsou pravděpodobně stejně zavlečené, zbytečné a tím pádem je můžu úspěšně ignorovat. A svět je zase sluníčkový...


Re:C++ a výjimka v destruktoru
« Odpověď #76 kdy: 06. 02. 2014, 09:36:36 »
Reference counting je povolený, ale navenek nesmí být vidět. To je hodně těžké udělat. Navíc s přibývajícími jádry není reference counting žádná výhra a pro krátké stringy je daleko rychlejší když je to krátké pole přímo uvnitř stringu.
 že si z STL celkem konzistentně vybíráš věci, které se úplně nepovedly a ty povedené naopak ne.

No  hádám, že jsi člověk z nějaké akademické půdy, který nikdy nic pořadnýho nenaprogamoval, ale jen tu obhajuje svojí víru. Zkus za použití pouze stl psát nějaký větší projekt, který by měl být rychlejší, než kdejaký skriptovací jazyk, nebo jazyk s překladem do bytecode, abys obhájil smysluplnost programování v C++? Velice záhi zjistíš, že ta milenka standardní knihovna je pěkná potvora a ještě k tomu líná.

Pro tvojí informaci, problém s reference countingem u řetězců není v tom, že by to bylo pomalé v moderních procesorech... Ono to pomale je, ale stejně to pomalé bude i bez reference countingu, protože to je obecný problém sdílení dat mezi jádry a jejich synchronizace. Ten problém je mnohem hlubší, už v základním návrhu. Já časem pochopil, proč je snaha zakazovat ref counting. Je to snaha dodefinovat návrh tak, aby odpovídal původnímu záměru a netrpěl problémy, který tomu časem zařídili jednotliví implementátoři.

Reference counting nemá být skrytý. Naopak má být viditelný. Programátor musí dostat do rukou nástoje , jak s tím pracovat. Základní problém std::string je ten, že se má chovat jako vektor znaků dle definice. V tu chvíli nesmí být sdílený. Jakékoliv operace přidání znaku, změna znaku a podobně nutně vedou na vytvoření kopie, která interně získá jinou adresu (c_str() začne vracet něco jiného). naopak std::string nemá rozhraní pro možnost kopii řetězce a pochopitelně nic neříká o tom, co se děje s řetězcem v MT prostředí. Všechny tyhle nedotaženosti vedou k tomu, že se to implementátoři snaží řešit obecně a detekovat všechny ty výše popsané situace, tak, aby se to chovalo jako pole znaků.

Pokud naopak řeknu, že řetězec je od počátku otevřeně sdílený s reference countingem a zakážu přímý přístup k řetězci (jakmile jednou LightSpeed::String vznikne, je const a nedá se jeho obsah změnit, lze jedině vytvořit nový řetězec s upraveným obsahem), definuju jak se řetězec chová v MT prostředí (ref counting ve výchozím stavu není  MT safe, takže se ty řetězce nesmí sdílet mezi vlákny, to je záměr) a dám k dispozici rozhraní pro možnost odstranit sdilení (metoda isolate() ) nebo vyrobení fyzické kopie (metoda copy() ), tak je to úplně něco jiného, co člověku přinese spoustu výhod a zabrání spoustu chybám a neočekávaným komplikacím, za předpokladu, že dodrží všechna pravidla s tím svázaná.

Já v té knihovně nemám jediný objekt na řetězce. Mám tam ConstStringT<T> - odkaz na libovolnou sekvenci znaků kdesi v paměti, StringPool<T> - kolekce řetězců vhodná pro řetězcové mapy, StringParam<T> - řetězec nebo reference podle použití, hodí se při vyhledávání v mapách (není třeba alokovat paměť, pokud chci najít určitý řetězec v mapě), samozřejmě AutoArray<T....> - což je stejné jako std::vector<T> nicméně tenhle objekt se dá převést na ConstStringT<T>. Z toho jsou odvozené objekty StaticString<T, n> a SmallString<T,n>, kde n udává maximální počet znaků. Alokuje se to pak přímo v tom objektu. Rozdíl mezi StaticString a SmallString je ten, že ten první má to n jako pevný limit, a při překročení háže výjimku. Ten druhý, SmallString, to číslo se chápe jako hint a při překročení to způsobí jen snížení výkonu, protože se musí alokovat na haldě.

Nic takového mi stl nenabízí. Jenom string

KRYTON: Aha. Přiblížit hlavu těsně... ehm, k předmětu. Dobře, chápu. A co další optické jevy: obrazová montáž, zpomalení, kvantel...
LISTER: Nic takovýho nemáme.
KRYTON: (Skepticky) Nemáte to, jenom zoom. (Komicky se naklání k seznamu) No, nic, to je dobré, to úplně stačí, opravdu výborné

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #77 kdy: 06. 02. 2014, 12:26:53 »
To já ne, to ten destruktor? Zastávám názor, že házení výjimek jen pokud to ničemu nevadí není řešení.

Co? Ukazoval jsem řešení, které zdestruuje dané pole, přičemž pokud dojde k výjimce, tak jej stále zdestruuje a zároveň ta výjimka vyletí.

Zdůvodním :
1) Pokud mi destruktory neházejí, vím, že se o chybách uvnitř destruktorů nedovím. Pokud se chci spolehnout, že všechno klaplo, musím to před zrušením objektu zkontrolovat.
2) Pokud mi destruktory házejí, tak vím že se o chybách občas taky nedovím. Pokud se chci spolehnout, že všechno klaplo, tak to musím taky zkontrolovat před zrušením objektu. A navíc musím samozřejmě chytat ty výjimky, takže místo jednoho místa ošetřuju stejnou chybu na dvou místech. A to se prostě vyplatí.

Anebo se na výjimky vykašlu rovnou, protože jinak tu chybu stejně ošetřuju na dvou místech. A to se prostě vyplatí.

Samozřejmě že můžu zapojit svou kreativitu a říct si že ty výjimky které se mi nelíbí jsou pravděpodobně stejně zavlečené, zbytečné a tím pádem je můžu úspěšně ignorovat. A svět je zase sluníčkový...

Anebo můžu přestat brát drogy a trochu se nad tím zamyslet ;)

Pokud se destruuje vnořený objekt, když jeho nadřazený objekt vyhodil výjimku (to je ten případ, kdy výjimku ignoruju), tak je mi úplně jedno, jestli ten vnořený objekt selže nebo ne. Ta operace na nadřazeným objektem už selhala, takže i kdyby ta chyba na vnořeném objektu nebyla zavlečená, stejně mě nezajímá.

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #78 kdy: 06. 02. 2014, 12:36:57 »
Pokud se destruuje vnořený objekt, když jeho nadřazený objekt vyhodil výjimku (to je ten případ, kdy výjimku ignoruju), tak je mi úplně jedno, jestli ten vnořený objekt selže nebo ne. Ta operace na nadřazeným objektem už selhala, takže i kdyby ta chyba na vnořeném objektu nebyla zavlečená, stejně mě nezajímá.

Co když to bude aplikace autopilota a ten destruktor vnořeného objektu bude nastavovat výškovku do defaultní polohy, aby letadlo letělo po ukončení autopilota rovně? Taky mě chyba ve vnořeném objektu nezajímá a v klidu ji můžu ignorovat, protože už vyletěla jiná výjimka? Sorry, ale na takovém předpokladu se žádná robustní aplikace postavit nedá.

Re:C++ a výjimka v destruktoru
« Odpověď #79 kdy: 06. 02. 2014, 13:15:47 »

Co když to bude aplikace autopilota a ten destruktor vnořeného objektu bude nastavovat výškovku do defaultní polohy,
Tak si autor takové aplikace koleduje sedět za obecné ohrožení.


Re:C++ a výjimka v destruktoru
« Odpověď #80 kdy: 06. 02. 2014, 13:27:35 »

Co když to bude aplikace autopilota a ten destruktor vnořeného objektu bude nastavovat výškovku do defaultní polohy, aby letadlo letělo po ukončení autopilota rovně? Taky mě chyba ve vnořeném objektu nezajímá a v klidu ji můžu ignorovat, protože už vyletěla jiná výjimka? Sorry, ale na takovém předpokladu se žádná robustní aplikace postavit nedá.

Pořád zapomínáte, že to že letí výjimka neznamená, že se ten destruktor neprovede, to jen znamená, že pokud ten vnořený objekt skončil chybou, tak už není možnost to někam hlásit, když už jedna výjimka je v běhu. Pořád si neuvědomujete, že když letí vyjimka, program zrovna neprobíhá standardně, takže od něj nelze čekat žádnou funkčnosy. Funkcí destruktoru je uvést stav vsech datových struktur, zdrojů a podobně do původního stavu in best effort. Pokud to u aplikace takto náročné opravdu nejde, je třeba zvážit, zda není lepší ten program ukončit. To je ale věc, kterou si autor rozhoduje při psaní toho objektu. Záleží jak moc důležitý objekt to je.

To fatální ukončení aplikace pak může spusti nějaký nouzový režim.

Nikdy nelze chybu ošetřit s tím, že dopředu říkáme, že ošetření chyby také může způsobit chybu. A když i to se pokusím ošetřit, tak i tam mohu způsobit chybu. A tak donekonečna. Někdy se musím rozhodnout, zda to vzdám, nebo to udělám jak nejlépe to jde. I za cenu třeba ztráty dat, pokud je pro mne stabilita víc, než nějaká ztracená data (třeba to byly jen statistická data, nebo data, která lze později rekonstruovat). Důležité je, aby to byl tvůrce té konkrétní třídy, kdo rozhodne, zda na chybu reagovat výjimkou (i za cenu nebezpečí double exception), nebo výjimkou pokud to jde, nebo zaignorováním. Když hromadně zakážu výjimky v destruktorech, beru autorovi svobodu a tlačím ho pouze do toho zaignorování.

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #81 kdy: 06. 02. 2014, 13:46:47 »
Co když to bude aplikace autopilota a ten destruktor vnořeného objektu bude nastavovat výškovku do defaultní polohy, aby letadlo letělo po ukončení autopilota rovně? Taky mě chyba ve vnořeném objektu nezajímá a v klidu ji můžu ignorovat, protože už vyletěla jiná výjimka? Sorry, ale na takovém předpokladu se žádná robustní aplikace postavit nedá.

Pokud autopilot spadne, tak je v tom letadle něco úplně špatně (třeba došlo ke flameoutu), takže jestli je špatně i výškovka, je v tu chvíli celkem maličkost.

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #82 kdy: 06. 02. 2014, 14:33:24 »
Pokud autopilot spadne, tak je v tom letadle něco úplně špatně (třeba došlo ke flameoutu), takže jestli je špatně i výškovka, je v tu chvíli celkem maličkost.

Autopilot se normálně vypne třeba proto, že fouká silný nárazový vítr a nedokáže udržet letadlo v přímém letu. To je normální stav, pilotovi se zahlásí alam o vypnutí autopilota a ten převezme řízení. Pokud autopilot při ukončení nedokáže nastavit řídicí prvky do nějakého definovaného stavu, pilot by o tom měl vědět. On se to ale nedozví, protože Sten rozhodl, že tyhle výjimky už nejsou důležité, stačí reportovat jen jednu.

Re:C++ a výjimka v destruktoru
« Odpověď #83 kdy: 06. 02. 2014, 14:57:21 »
Autopilot se normálně vypne třeba proto, že fouká silný nárazový vítr a nedokáže udržet letadlo v přímém letu. To je normální stav,

To ukazuje na chybné použití výjimky. Vadnou část jsem potrhnul.

sobol

Re:C++ a výjimka v destruktoru
« Odpověď #84 kdy: 06. 02. 2014, 16:37:14 »
Jako prvotnímu dotazovateli si myslím, že i když je to možný, tak výjimky do destruktoru nepatří. To, že to jazyk umožní, nepovažuju za feature oop. Je to jako protimluv. Chtel jsem nasimulovat, co by se stalo a jak s tím naložit, kdyby k tomu došlo.

Neporozuměl jsem, že se mi ve VS2013 ani nevypíše, že došlo ke konstrukci objektu.

Honza

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #85 kdy: 06. 02. 2014, 16:53:37 »
To ukazuje na chybné použití výjimky. Vadnou část jsem potrhnul.

Nikoliv, autopilot se vypne (bez výjimky), to je normální stav. V destruktoru klapek vznikne výjimka "nemůžu nastavit klapky" a poté vznikne v destruktoru výškovky výjimka "nemůžu nastavit výškovku". Pilot se dozví, že má blbě klapky, ale už se nedozví, že mu letadlo padá kvůli blbě nastavené výškovce. Jestli to přežije, tak bude proklínat programátora, který si myslí, že vyhazovat výjimky v destruktoru je v pohodě.

kuka

Re:C++ a výjimka v destruktoru
« Odpověď #86 kdy: 06. 02. 2014, 16:57:42 »
Co když to bude aplikace autopilota a ten destruktor vnořeného objektu bude nastavovat výškovku do defaultní polohy
Pokud bude destruktor neco nastavovat, tak to je predevsim blbe navrzene.

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #87 kdy: 06. 02. 2014, 17:07:30 »
Pokud bude destruktor neco nastavovat, tak to je predevsim blbe navrzene.

S tím samozřejmně souhlasím a to vede na řešení:
Destruktor nedělá pokud možno nic sofistikovaného a ošetření chybových stavů patří mimo destruktor, z čehož vyplývá, že destruktor nevyhazuje výjimky :).

Re:C++ a výjimka v destruktoru
« Odpověď #88 kdy: 06. 02. 2014, 17:29:18 »
Pokud bude destruktor neco nastavovat, tak to je predevsim blbe navrzene.

S tím samozřejmně souhlasím a to vede na řešení:
Destruktor nedělá pokud možno nic sofistikovaného a ošetření chybových stavů patří mimo destruktor, z čehož vyplývá, že destruktor nevyhazuje výjimky :).

Destruktor zejéma uklízí zdroje. A pokud se při úklidu zdrojů objeví chyba, tak za normálního běhu by měl o tom informovat výjimkou. Pokud se však objeví chyba při úklidu během stack unwind, tak taková výjimka už beztak nemá žádný smysl, protože bude z 99.9% souviset s již probíhajícím chybovým stavem.

Víc k tomu nemá co smysl psát. Myslím, že to je jasné a zřejmé. Jestli to děláte jinak, je to váš problém

Tomáš Marný

Re:C++ a výjimka v destruktoru
« Odpověď #89 kdy: 06. 02. 2014, 17:46:18 »
To ukazuje na chybné použití výjimky. Vadnou část jsem potrhnul.
Jestli to přežije, tak bude proklínat programátora, který si myslí, že vyhazovat výjimky v destruktoru je v pohodě.

V softwaru pro použití v kritických oblastech, jako je třeba toto nebo řízení v průmyslu, se velmi mnoho věcí, jež jazyk umožňuje, zcela zakazuje používat - právě z důvodů, že je o tom možné vést takovéto debaty a důsledky jsou dosti nepredikovatelné. Takže nějaké vyhazování výjimek v destruktoru v SW letadla rozhodně nehrozí. :) Jen pro zajímavost - v SW pro řízení elektráren je zakázáno i pouhé přetěžování operátorů, natož takovéhle věci.