Zobrazit příspěvky

Tato sekce Vám umožňuje zobrazit všechny příspěvky tohoto uživatele. Prosím uvědomte si, že můžete vidět příspěvky pouze z oblastí Vám přístupných.


Příspěvky - Ondřej Novák

Stran: 1 ... 14 15 [16] 17 18 ... 38
226
Vývoj / Re:C++ a výjimka
« kdy: 12. 02. 2014, 15:40:31 »
pouze 2 stavy: OK/ERROR. To ze "ERROR" v sobe obsahuje bazilion ruznych chyb je v tomto pripade mozne ignorovat. Podstatne je pouze osetrit CELY stavovy prostor - jak detailne uz zavisi na tom, co od aplikace ocekavame.
S timto pristupem neni reseni chyb nijak komplikovane ani s chybovymi kody.
Znám spoustu programů, které, když se jim něco nelíbí, tak napíšou "ERROR" a skončí.

Takove objekty musi mit jasne definovane rozhrani - a tedy zpusob jak zjistit zda selhaly (a opet je jedno jestli nejakym try/catch nebo osetrenim errorcodu). Ve vetsine pripadu staci brat opet pouze 2 stavy - externi objekt selhal, nebo neselhal. Osetreni opet trivialni.

Samozřejmě, že je ošetření trivální. ERROR  ;D

1) Ja jsem zminoval glib - jeji GError resi nejen nekolidovani (internovani textovych identifikatoru chyby pri jeji definici) ale i hierarchii (plus prilozeni dalsich informaci k chybe, coz jste z me neznamych duvodu pokladal za nejakou vymozenost vyjimek)
Vidíte! A ony přesně výjimky takhle fungují. Jediný co mají navíc je to, že nemusíte psát kolem volání IFy
Kód: [Vybrat]
if (!foo()) return 0;
if (!bar()) return 0;
if (!fee()) return 0;
pokud nastane chyba ve foo, tak vyhozená výjimka jedná ve stejném duchu, jako výše uvedený zápis, udělá return s nějakým chybovým příznakem, aby nadřazená funkce věděla, že nastala chyba. Vám ušetří psaní. Informace o výjimce se drží v nějaké statické TLS proměnné, odkud se pak vyzvedávají v handleru.

Proč teda vy lidi máte takovou averzi vůči výjimkám, když jde jen o syntax-suggar?

Výhodou výjimek je to, že fungují stejně třeba i ve Windows, kde není glib a ani GError
2) rucne v jednom enum-u v jednom globalnim hlavickovem souboru pro chyby (idealne automaticky generovanem z nejakeho textaku kde je k chybe doplnen i jeji lokalizovatelny textovy popis)
Globální hlavičkový soubor... vy asi nepíšete knihovny?

3) "neresim" - kazdy "modul" (napr. foo.c, foo.h) ma sve errorkody s prefixem "ERROR_FOO_" - jejich skutecna integer hodnota nemusi byt nijak unikatni, protoze selhani modulu "foo" musi resit kod, ktery ho vola a protoze "foo" muze vratit pouze "ERROR_FOO_*" kody, neni zadny duvod pro jejich unikatnost.
A z modulu FOO vyhodíte chybu do modulu BAR tak že nadefinujete proměnnou ERROR_BAR_ERROR_IN_FOO a tu zareportujete ven. Co se vlastně ve FOO stalo, to už se nikdo nedozví. Když to neuděláte vy, tak to udělá váš nějaký méně zdatný kolega. Nebo to udělá proto, že mu na vývoj modulu nadřizený přidělil málo času (pak je 1000x lepší, když vylítne výjimka přímoz FOO, než když ji někdo zahodí a vyhodí obecnou chybu)


To je asi jakoby Vam Firefox pri nezdarenem pokusu o otevreni stranky vypsal HTTP odpoved, TCP/IP packety, ethernetove pakety, atd, atd.
Co myslíte, jak mi je, když mi Firefox napíše, že "Stránka se nedá zobrazit" (aby třeba k tomu dodal, že DNS jméno neexistuje, nebo že selhalo spojení, což mi třeba napoví, že jméno mám správně, ale blbec jsem si nohou vykopnul kabel z ethernetu)

pouze jeden chybovy stav pro selhavsi "fopen" - neco ve stylu: ERROR_CONFIG_OPEN("Couldn't open configuration file myapp.cfg"). Presny errorcode proc "fopen" selhal neni nutne uvadet.

Opět jeden příklad z praxe. Neustále to hlásilo, že to nemůže otevřít nějaké datové soubory. Dokonce někoho chytrého napadlo, že by bylo dobré uživateli napovědět, co má dělat. Ať si prý zkontroluje, zda tam ty soubory jsou. No byly tam, ale program stále tvrdil, že tam nejsou. Až po podrobném prozkoumání problému pomocí strace se ukázalo, důvodem, proč to nejde je chyba "Access Denied". Po úpravě přístupových práv k těm souborům se to už rozběhlo. Jistě, že to někoho mohlo napadnout předtím, ale nenapadlo... celé odpoledne zabyté jen tím, že autor programu měl podobný názor jako vy.

Pane Novak, nechci Vas nebudu obvinovat z neznalosti, nedostatecnych "1337 skillz", nebo podobne. Ale ja jsem v C delal uz na 3 netrivialnich projektech, a vetsinu Vasich namitek co "nejde" bez vyjimek, jsem mnohokrat a bez vetsich problemu resil.
Ale tim, ze "predpokladate", ze to v C nejde (protoze delate v C++), se stavite presne do te pozice cloveka, ktery neco nezna, nepouziva to, ale je presvedcen ze o tom vse vi a vi proc je to spatne a proc je to co pouziva on lepsi.

Jen 3?  ;D  ;D  ;D  ;D

227
Vývoj / Re:C++ a výjimka
« kdy: 12. 02. 2014, 10:31:00 »
Ošetřit všechny chybové stavy přece není o genialitě, ale o důslednosti. Prostě si navrhnu nějaké rozhraní a při implementaci kouknu do dokumentace na všechno co volám a ošetřuju všechny možné běžné i vzácné stavy. Všechno s čím se dokážu vypořádat na fleku se vypořádám tam. To, co nedám, předám ven. V některých případech to znamená i úpravy rozhraní. Tohle je postup, který nezávisí na tom, jestli se používají výjimky nebo chybové kódy.
No máte a nemáte pravdu. Samozřejmě, že chybové stavy vyplývající z činnosti volaného programu/metody/funkce/whatever by mělo být ošetřeno uvnitř a vypadávat ven tak, jak bylo navrženo. Chybové stavy nějakého stavového automatu jsou stavy toho automatu, ne výjimky (k tomu se výjimky nepoužívají).

Nevím, kolik máte za sebou praxe, ale určitě víte, že člověk málokdy píše konečnou funkcionalitu, která dále nezávisí na jiných neznámých. Jednou neznámou je třeba fungování platformy. Proto jsem se ptal, jestli jsou mezi námi tak geniální nebo důslední programátoři, že jsou schopni ošetřit všechny chybové stavy. Protože považte, kolik chybových stavů má jenom funkce fopen

http://www.root.cz/man/3/fopen/

Druhou neznámou jsou dodané objekty z venku, které mohou neočekávaně selhat. Například callback funkce, handlery všelijakého druhu a podobně. Je třeba mít mechanismus, jak s tím naložit

Pokud používám chybové kódy, tak moje rozhraní musí předat ven všechny chyby, se kterými se nedokážu vypořádat uvnitř.
Jak zajišťujete nekolidování chybových kódů


Pokud používám výjimky, tak musím minimálně v rozhraní zdokumentovat všechno, co může vyletět z funkcí, které volám uvnitř. Případně můžu ty výjimky vyhozené uvnitř vylepšit nebo konvertovat na něco, co bude venku dávat větší smysl.
O tom, jestli je to víc práce s kódy nebo s výjimkami se dá diskutovat. Ale ta stěžejní část, kdy musím kouknout do manuálu a všechny možné chyby promyslet, je u obou přístupů úplně stejná. Zbytek už je vlastně jen mechanická práce.

To je otázkou, zda vnitřní výjimky odchytávat a přebalovat je na nějaké vnější výjimky, které jsem si  pro tento účel vytvořil. Má to několik háčků.
  • Přebalením do jiné výjimky ztrácím zpravidla informace, které často mohou být cenné - z toho důvodu používám po vzoru Javy tzv. Reason. Sice přebalím výjimku, ale původní výjimku vložím k nové výjimce jako reason. Taková výjimka se třeba pak zaloguje: "Exception - unable to open session, because: can't connect service provider, because: can't create connection to localhost:17700" - takováhle výjimka má v sobě hned dva reasony zřetězené za sebou jak byly slepovány když letěly ven - tenhle systém vyžaduje mít propracovaný výjimkový systém
  • Přebalením do jiné výjimky mohu zmást volajícího, za předpokladu, že se mi podaří přebalit výjimku, kterou vyhodil jeho objekt, se kterým se pracovalo - volající očekával, že poletí výjimka z jeho objektu, ale ve skutečnosti letěla jiná výjimka a propadla až na základní úroveň - fail
  • Někdy může být problém zdokumentovat všechny možné výjimky letící ven, když není známo v jakém prostředí bude algoritmus fungovat. Například se vám může stát, že vám někdo podstrčí virtuální filesystem, na kterém létají naprosto odlišné výjimky, než jste zvyklý - (má knihovna má přístup na fs přes rozhraní, které jde přepsat vlastní verzí, aniž by na první pohled bylo poznat, že program nepracuje s fyzickým diskem, nebo s fyzickou sítí, například)


I tady je třeba postupovat opatrně a z rozvahou.



228
jestli někdo píše generátor wraperů, jsem první zákazník. V C++ mi tahle vlastnost chybi uz hrozně dlouho (moznost generikou generovat metody ktere nejsou deklarované na třídě podle jiného rozhraní a jejich vykonáni prostým delegováním pres pointer)

229
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 11. 02. 2014, 23:59:27 »
Jenže existují oblasti programování, kde si prostě nemůžete dovolit spadnout za žádnou cenu (resp. ta cena je velmi vysoká). Tam jsou vám všechny ty výjimky na nic, protože hrabat se z těch sítí zpátky na místo, odkud jste do nich slítli, je dost náročné.
Výjimka != pád

Prosím naučte se to rozlišovat. Dokonce synchronní výjimky jsou prostě jinou cestou návratu (ten návrat je řízený). Tzv. asynchroní výjimky (výjimka může vzniknout kdekoliv, třeba v signal handleru) já nepoužívám a nikdy nebudu. Výjimka je prostě jen způsob, jak opustit funkci jinudy. Je to něco jiný typ returnu. Nic víc.

Zpracovávat chybový stav jinde, v jiném kontextu, než kde nastal, je prasárna. Jak už tu padlo, principiálně totiž žádný chybový stav vlastně neexistuje. Je to prostě jen jeden z možných stavů a tedy neexistuje žádný rozumný důvod, proč kvůli němu skákat někam mimo kontext.
Vy musíte být geniální programátor, že jste schopen ve svém programu podchytit všechny chybové stavy? Jen si vemte, kolik chybových stavů mají všechna systémová volání, které ve svých programech používáte. Opravdu jste schopen všechny tyhle stavy ošetřit. Na všech úrovních (!)?. A máte jistotu, že to někdo ošetřuje nad vámi (ve hierarchii callstacku)?

To už výjimky můžete rovnou použít k předávání návratových hodnot.
To teda nemůžete. To byste byl teprve prase. Výjimky ani nejsou dělané na takovou věc. Už jen optimalizace kódu se provádí na standardní běh, zatímco zpracování výjimky bývá často velice pomalé (při porovnání s běžným chodem). Naopak, když výjmky nepoužijete a ošetřujete chybové stavy každého volání, program v normálním běhu moc optimální nebude. Každý if znamená jeden odhadnutý skok, který se nemusí vždy povést správně odhadnout a procesor se vám tam zastaví na vyprazdňování fronty. Výjimky tímto netrpí.

230
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 11. 02. 2014, 21:49:51 »
to ze se na poolove operaci nebude provadet zadne dynamicke new/delete beru za samozrejmost, k tomu vetsinou slouzi ty ruzne pametove ci kontextove pooly:-)
ono je taky fajn,pokud chces at nejaky program bezi dele nez tyden, tak se celkove vyvarovat jakyhkoli dynamickych alokaci,pokud je to principialne mozne....

To mě fakt netrápí. Server má 4GB paměti, aplikace zabírá s bídou 100MB (RES). Pokud už padá, tak kvůli něčemu jinému, než kvůli paměti.

(jo mám tam watchdog, který ho rychle nahodí zpět, takže 99.9999999% uživatelů to nepozná, takže nám to jen kazí statistiky).

231
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 11. 02. 2014, 21:45:33 »
Zajimave videt, jak se "high availability" da pojmout ruzne. U nas to znamena nasledujici:
- Zadna dynamicka alokace pameti. Nikdy.

To asi porovnáváme neporovnatelné. Věřte mi nebo ne, ale moje knihovny v současném návrhu (i s výjimkami) se například vůbec nedají použít v Arduinu. A to ani kdybych ty výjimky nějak vyházel. Prostě tam se programuje naprosto jinak a jen díky tomu, že to nedělám denně, nemám na to vytvořené žádné kopyto (konečně o kopytech to celé je, záleží kde a co šijete)

232
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 11. 02. 2014, 21:36:22 »
Ještě bych uvedl jednu dobrou věc na výjimkách obecně. Od té doby, co je používám jako výhradní způsob hlídání chyb mi odpadla jakákoliv práce s vytvářením systémů chybových kódů. Výjimka je samo popisná. Moje výjimky dokonce (povinně) musí hlásít i místo vzniku (__FILE__ a __LINE__) - naštěstí na to mám makro.

Kód: [Vybrat]
throw FileNotFoundException(THISLOCATION, filename);
(ano, je to to makro THISLOCATION, které inicializuje objekt ProgramLocation)

- nevěřili byste jak je to užitečné. Na serverech je to užitečné vždycky, protože když se něco stane, v logu je to většinou dost popsané. Ale já to používám i na desktopových aplikacích. Každá aplikace generuje nějaký log. Někdy je ten log ukládaný jen do paměti, jindy i na disku. Pokud aplikace začne zlobit a uživatel bombarduje helpdesk svými dotazy a stížnostmi, helpdesku zpravidla stačí zaslat log. No a buď sám helpdesk z logu pozná, o co jde (jedná se třeba o částý problém), nebo to poznám později já.

Všimněte si další vlastnost
. Já s výjimkou ukládám i jméno souboru, které se nepodařilo otevřít. Tohle je prakticky nemožné zařídit systémem návratových hodnot. Pak vám aplikace nahládí "něco selhalo" nebo "soubor se nepodařilo otevřít" nebo "file not found" a nebo vám vrátí exit code 2. A teď hledejte, co se nezdařilo.

Další vlastností je výjimková hierarchie. Vytváření kategoríí výjimek. Mám základní sadu výjimek které dědí Exception. Pak výjimky ze skupiny SystemException nebo NetworkException. Threadové výjimky jsou zpravidla pod ThreadException. Souborové výjimky jsou pod IOException.

Samozřejmě mě v tom inspirovala Java (jako většina věcí)

Protože kategorie mají povinnost dědit virtuálně Exception, je povoleno dědit z vícero kategorii.

Kód: [Vybrat]
class MujProblemSeSiti: public SystemException, public NetworkException {
...
};
Já si pak na místě, kde to potřebuju mohu vybrat zda napíšu

Kód: [Vybrat]
catch(MujProblemSeSiti &e)

catch(NetworkException &e)

catch(SystemException &e)

Kód: [Vybrat]
catch(FileNotFoundException &e)

catch (IOException &e)
nebo když nevím

Kód: [Vybrat]
catch (Exception &e)

a nebo velimi obecné (odchytne drtivou většinu výjímek)

Kód: [Vybrat]
catch (std::exception &e)

handler na základní úrovni  by měl být schopen odchytnout i jinak nerozpoznanou výjimku (které ale nesmí v mých programech nikdo házet, pouze ve speciálních případech, pokud je cílem, aby výjimka nebyla odchytnuta a zahozena)

Kód: [Vybrat]
catch (...)

Jak tady někdo psal, že to sklouzává k  tomu, že výjimky se nechávají propadnout až na základní úroveň, místo aby je někdo zpracoval, tak to teda není pravda. Zpravidla na tom rozhodujícím místě dochází k větvení

Kód: [Vybrat]
catch(Vyjimka1 &e) { reportError(333, e);}
catch(Vyjimka2 &e) {reportError(666, e);}
catch(ObecnejsiVyjimka &e) {reportError(500, e);}
catch(std::exception &e) {reportGeneralError(e.what());}

Pokud někomu vadí, že musí generovat hromadu catch handlerů na konci obsluhy každého handleru, tak nemusí, dá se to udělat takto:

Kód: [Vybrat]
void processErrors() {
try {
  throw;
} catch (A a) {
...
} catch (B a) {
...
} catch (C a) {
...
} catch (D a) {
...
}
}

void handler () {
try {
....
} catch (...) {
 processErrors();
}
}

Zpět na začátek. Hlavně jsem se zbavil definování tisíců chybových kódů a hlídání toho, zda někde nekolidují. Každá knihovna měla vlastní kódy. Díky výjimkám je každá chyba přesně specifikována a zařazena do kategorie. Uvnitř aplikace létají výjimky a na vnějším rozhraní... pokud si to zadavatel přeje ... mám každé výjimkové třídě přidělen nějaký unikátní kód. A protože se to zpravidla řeší na jednom místě, není problém udržet ten seznam kódů bez kolizí.

233
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 08. 02. 2014, 22:15:26 »
1) Connection conn = mysqlpool.get();
hm normalne by clovek ocekaval ze pool cehokoli me spis vrati adresu a ne hodnotu ale budiz treba to tak je netusim jak je ta tva Conection deklarovana pripadne velka/slozita/konstruovana...

Tenhle způsob může být právě docela fajn. Ta instance se mu vytvoří pěkně přímo na zásobníku, takže ušetří za volání new/delete. Navíc s opuštěním bloku se ten objekt může i automaticky sám uklidit (vrátit spojení do poolu).

On je tam vlastně ukazatel na mysql connection a destruktor, co vypůjčenou konekci vrací do nějakého kontejneru a samozřejmě ukazatel mysqlpool, aby to vědělo, kam to má vrátit. Samo se předpokládá, že v době destrukce ten mysqlpool bude ještě existovat, ale chyby tohoto druhu se stávají výjimečně.

234
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 08. 02. 2014, 22:12:03 »
2) Transaction trn(conn);
kdyz odmyslime trivialni variantu na if(conn.valid()) ktera dela obrovsky ifovy overhead kolem tak se to da rozumne poresit uvnitr toho konstruktoru aby na nevadilni connection vznikla reguleni nevalidni transaction co na jakykoli nasledujici command jako...
Result res = trn.SELECT("*").FROM(...).....;
proste nic taky neudela, to plati i na ten nasledujici commit()

kdyz to bude reseno uvnitr,navenek ten kod muze byt uplne identicky jak ten tvuj, zadny if-ovy balast kolem a presto nemusi nikdy generovat vyjimky. konkretni realizace je spis zavisla na cetnosti/pravdepodobnosti nevalidnich stavu z hlediska performance....
Tohle snad není myšleno vážně, že ne. A co ten selekt jako vrátí za data, když bude ta transakce nevalidní? Prázdnou tabulku? Co když tam bude SELECT NOW(); který evidentně prázdnou tabulku nemůže vrátit. Co když tam bude nějaký super extra dlouhý a komplikovaný výpočet, který navíc bude záviset na datech v té databázi, takže při prázdných tabulkách bude trvat neuvěřitelně dlouho, nebo se dostane do nekonečné smyčky? Třeba proto, že to mělo něco do databáze zapsat a následně vyzvednout něco jiného, co tam nebude, takže se to bude do nekonečna opakovat? Člověče, že vás tady vůbec školím. Doporučuju se od programování držet v uctihodné vzdálenosti, a zabývat se třeba ... já nevím, tvorbou webovek v PHPku....

To jsem ještě neviděl! Jo studenti v prvním ročníku mají takové děsivé nápady.

235
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 08. 02. 2014, 17:35:58 »
btw mozna i casove by bylo jednodusi napsat lepe ten ohandlovany kod nez se drbat pravou rukou na .... a rozjimat o vyjimkach v destruktorech na akademicke urovni....

Vůbec netušíš o čem mluvíš. Kód, který tady řeším vypadá takto:

Kód: [Vybrat]
{
Connection conn = mysqlpool.get();
Transaction trn(conn);
Result res = trn.SELECT("*").FROM(...).....;
....
trn.commit();
}

Z každého příkazu může vylítnou výjimka.
Z mysqlpool.get() například když dojdou spojení v poolu a vyprší timeout
Z transaction v okamžiku, kdy databáze odmítne příkaz BEGIN
Z sql příkazu může vylítnout cokoliv, třeba když napíšu ten dotaz blbě, nebo když databáze mezitím spadne
Z commitu může vypadnout taky víceméně cokoliv, pokud to databáze odmítne commitonouy

Víceméně všechny výjimky odchytává rpc server, ihned po návratu z handleru a vrací na to chybu 500. Zároveň do logu zapisuje chybovou hlášku, která vylítla s výjimkou.

Dám ti úkol. Napiš to bez výjimek. A zkus to navrhnout tak, aby se takový kód dal použít třeba 234x (zhruba tolik metod má můj server na svém RPC rozhraní) - poznámka pro rejpaly, ono to tělo není vždy úplně stejné a některé metody tedy databázi nepotřebují, ale moc jich není.

Ta akademická diskuze je jen o tom, jestli mají létat výjimky z té časti mezi posledním příkazem a složenou závorkou (třeba při rollbacku transakce, nebo chyba při vracení spojení do poolu.

236
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 08. 02. 2014, 15:58:06 »


Tenhle příspěvek je zbytečný. Ani oddělení autopilotů na samostatné počítače a jejich restart (restart celých počítačů v době chyby) neznamená, že to vždy bude konzistentní. Už jsem viděl dost chyb založených na tom, že nějaký řídící program zanechal svěřený prostředek v nekonzistentním stavu a po restartu nebyl schopen práce. Bylo nutné jít a manuálně uvést ten prostředek do počátečního stavu, aby se řídící program chytil ... byl to nějaký souřadnicový řezací stroj ... ano, měl i standardní inicializaci, ale ono to bylo složitější.

Od té doby mám rád výjimky, protože je tu pořád slušná šance, že při chybě budou k dispozici data potřebná k nápravě. Když program spadně sigsegv, nelze o jeho stavi nic říct. Když je od někud vyhozená výjimka, jedná se o řízený pád, kde každý komponenta vzniklá během činnosti dostane informaci o tom, že se něco děje a může na to vhodně reagovat. Process je to řízený, takže není nebezpečný, naopak nebezpečné je to nechat spadnou. A neberu ani argument, že to takhle dělají nějaké přetechnizované firmy s vysokým stupněm zabezpečení. Z téhle diskuze je vidět, že výjimkám ještě hodně lidí nerozumí a tak je pro zodpovědné osoby mnohem snažší a bezpečnější spolehnout se ještě na jiné technologie.

Nehledě na oblíbený problém zakonzervovaných seniorů, kteří se těší důvěře produktových managerů a jinak mají na celý problém přesně ten názor, jaký zde prezentujete, aniž by bylo podpořen jediným argumentem


237
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 08. 02. 2014, 14:30:58 »
Což o to leaky mi kontrolují různé nástroje a nikdy jsem si žádného nevšiml. Asi zpravidla proto, že většinou jde o objekty, u kterých se předpokládá, že vzniknou na zásobníku. Má oblíbená architektura totiž vypadá takto

1.  objekt co vlastní zdroj
2.  objekt co s ním manipuluje (manipulant - builder)

Ten co vlastní zdroj, ten bývá často (ale ne vždy) alokován dynamicky. Naopak builder bývá výhradně na zásobníku. Builder většinou v destruktoru uvádí zdroj do konzistentního stavu, tak aby se případně dal používat s nějakým dalším builderem. Pokud by builder nedokázal zanechat zdroj v konzistentním stavu, tak je to fatal error a právě zde se má / měla hodit výjimka. Nedokážu si představit, že by se to zaignorovalo. Případný další builder bude pracovat s nekonzistentním zdrojem... NO WAY... to je těžkej malér.

Jediný co mě napadlo, jak by se to dalo řešit je výjimku forwardovat budoucímu builderovi, který ji výhodí v konstruktoru. Znamená to ale, abych si u zdroje vedl jeho stav, nebo ještě jednodušeji, abych výjimku zachycenou v destruktoru místo vyhození uložil do objektu držící zdroj.

Ani to neřeší problém 100%. Pokud mám pool zdrojů, třeba databázových spojení a já uložím do poolu nekonzistentní zdroj (protože jsem se nedozvěděl, že je nekonzistentní, žádná výjimka nevylítla), tak i forwardovaná výjimka vylítne tomu, kdo další takový zdroj vytáhne z poolu. A ohlásí chybu  ... to může být třeba další request na serveru... chyba se ohlásí tedy někomu, kdo za to nemůže... NO WAY!

Takže mě ještě napadl další workaround. Dodělat do všech možných zdrojů, které mám, kromě funkce forwardování výjimky, taky funkci na kontrolu integrity (checkIntegrity()). Tato funkce by mohla hodit forwardovanou výjimku. Před uložením do poolu by se to zavolalo a pokud by výjimka vylítla, tak by se zdroj rovnou zlikvidoval a do poolu by se nevracel. Bohužel, vracení do poolu je realizováno v destruktoru  :D Takže onu výjimku si mohu maximálně strčit ... někam do logu.

Ještě příklad. Když mi v destruktoru transakce falíruje operace rollback, už nemám šanci se to dozvědět (a to ani v případě, že neletí žádná výjimka) a maximálně při vracení mysql spojení do poolu mohu ověřit, jestli tam není někde forwardovaná výjimka a pokud ano, tak ji zalogovat a z databáze se odpojit ... snižit počet aktivních spojení z databází, pool pak vyrobí novou konekci.

Uff a to je kvůli tomu, že mi selhal rollback

238
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 08. 02. 2014, 10:51:33 »

Intel C++ Compiler delete nezavolá, stejně tak (zdá se) Visual Studio 2010. Kde to ale funguje je clang++.

Potvrzuju, clang-3.3 (Ubuntu 12.04 LTS) funguje jak má

 
Kód: [Vybrat]
ondra@cornelie:/tmp$ clang++ raw.cpp 
ondra@cornelie:/tmp$ ./a.out
create
new
destroy
destruct
delete
exception 1
ondra@cornelie:/tmp$

Mimochodem, o existenci clangu jsem doposud nic nevěděl. Jdu ho vyzkoušet.

239
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 08. 02. 2014, 00:22:35 »
Jak jsem říkal a vracím se k třetímu příspěvku. Chce to prostě vyzkoušet. Jedna věc je, co říká norma, druhá věc je, co implementují překladače.

GCC 4.7.1 - delete nezavolá
na codepadu je verze 4.1, ale chová se to stejně

http://codepad.org/z5NtbxMy

nezavolá ani když má virtuální destruktor

http://codepad.org/X7utHYHZ

přičemž normálně by se volat měl

http://codepad.org/HHKUxfYq

Chová se to naprosto stejně i v případě, že zapnu std=C++11

Jak je na tom Visual Studio?
Mám jen verzi 2008. V pondělí mohu zkusit 2010

Visual Studio je na tom stejně. Navíc dokonce visual studio nezavolá ani standardní delete a nechá paměť leaknout.

Smutné. Takže ani jeden z předních překladačů neimplementuje normu správně.  Zajímavý je, že o chybě se diskutovalo už v roce 2002
http://wg21.cmeerw.net/cwg/issue353

240
Vývoj / Re:C++ a výjimka v destruktoru
« kdy: 07. 02. 2014, 23:38:27 »
Mimochodem zajímalo by mě, jak se dá s výjimkou v destruktoru vyřešit tohle:
Kód: [Vybrat]


Bugy jsou bohužel v každém software

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55635

Stran: 1 ... 14 15 [16] 17 18 ... 38