C++ a výjimka v destruktoru

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #45 kdy: 05. 02. 2014, 15:26:09 »
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.

Proč jste to psal znovu a nepoužil třeba tohle?
http://fastformat.sourceforge.net/


JSH

Re:C++ a výjimka v destruktoru
« Odpověď #46 kdy: 05. 02. 2014, 15:26:32 »
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 :)
std::shared_ptr<FILE> f(fopen(...), fclose); je vlastní stream?

Re:C++ a výjimka v destruktoru
« Odpověď #47 kdy: 05. 02. 2014, 15:33:09 »
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.

Proč jste to psal znovu a nepoužil třeba tohle?
http://fastformat.sourceforge.net/

Protože jsem potřeboval binární streamy. Vůbec nakonec moje streamy žádné formátování nemají. Formátování řeší objekt TextOut, který dostane jako parametr binární stream. Asi jsem trochu nakažený javou.

Re:C++ a výjimka v destruktoru
« Odpověď #48 kdy: 05. 02. 2014, 15:37:04 »
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 :)
std::shared_ptr<FILE> f(fopen(...), fclose); je vlastní stream?

Aj, std::shared_ptr, zachraň se kdo můžeš   ;D

Kvůli pitomosti volat pomalej new  ;D

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #49 kdy: 05. 02. 2014, 15:42:27 »
Aj, std::shared_ptr, zachraň se kdo můžeš   ;D

Kvůli pitomosti volat pomalej new  ;D

Režie fopen je mnohem větší než režie new. Takže znovu: premature optimization is the root of all evil


Re:C++ a výjimka v destruktoru
« Odpověď #50 kdy: 05. 02. 2014, 15:49:01 »
Aj, std::shared_ptr, zachraň se kdo můžeš   ;D

Kvůli pitomosti volat pomalej new  ;D

Režie fopen je mnohem větší než režie new. Takže znovu: premature optimization is the root of all evil

Ale to je pitomost. Proč mám sakra zbytečně zdržovat svůj program když na to už mám napsaný nástroj, který nic alokovat nepotřebuje? Proč? Jenom proto, že režije fopenu je mnohem větší, tak mi musí vadit těch pár mikrosekund (což mohou být i milisekundy, když se new umlátí na zámku s nějakým jiným vláknem). Jenom proto, že někdo slavný prohlásil takovou pitomost? Je jasné, že snažit se optimalizace tam kde to nemá cenu je  blbost, ale pokud je to pro mne jen změna knihovny a jména objektu, tak to smysl má.

Problém totiž je vtom, že tyhle mantry opakují všichni, aniž by se nad tím zamysleli. Tady to asi nemá velký význam, ale pak vidím kód, kde se to zneužívá až tak, že jediné co program dělá je, že tráví většinu času v knihovnách STL. Jen proto, že někdo kdosi kdysi řekl, že premature optimization is the root of all evil.

A tak všichni používají třeba string i tam, kde by stačilo třeba const char *. Jenže to není podle mantry, takže je to evil. Hnusi se mi tenhle masový styl.

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #51 kdy: 05. 02. 2014, 16:16:19 »
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 :)
std::shared_ptr<FILE> f(fopen(...), fclose); je vlastní stream?

Tohle má ten drobný detail, že pokud fopen selže (nebo někdy zavoláte reset), tak se fclose zavolá na nullptr. SIGSEGV.

Mr. Obvious

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

+1

Mr. Curious

Re:C++ a výjimka v destruktoru
« Odpověď #53 kdy: 05. 02. 2014, 16:37:04 »
Pane Novak, jen me tak napada. Minule jste popisoval svoji lasku k open source. Nemate nekde tu vasi LightSpeed STL-killer knihovnu nekde ke shlednuti?

Mr. ReadWholeForum

Re:C++ a výjimka v destruktoru
« Odpověď #54 kdy: 05. 02. 2014, 16:58:35 »
To teda nemam (Novák)

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #55 kdy: 05. 02. 2014, 21:26:44 »
Tohle má ten drobný detail, že pokud fopen selže (nebo někdy zavoláte reset), tak se fclose zavolá na nullptr. SIGSEGV.
Jo, to je pravda. Pozapomněl jsem na to, že fopen kontroluje null jen v některých implementacích. Chtěl jsem napsat ilustrační příklad a nedomyslel jsem ho. Osobně používám unique_ptr, ale nechtělo se mi sem psát ten funktor.

Navrch je tam stejný problém o kterém se tu stále diskutuje - nekontroluju návratovou hodnotu a ve vzácných případech to může být problém.

Co mě ale fascinuje je, že se Ondra Novák chytl na ten nejmenší problém s tímhle kódem. Ne, řešit jednu dynamickou alokaci paměti u diskových operací mi prostě hlava nebere. I když zanedbám pomalost disku, tak ovladač tam bude alokovat, operační systém tam bude alokovat, standardní knihovna tam bude alokovat a já se mám alokaci vyhýbat abych nemrhal výkonem.

Škoda že nejspíš nikdy neuvidím zdrojáky té LightSpeed knihovny. Zajímalo by mě, jak je tam řešená realokace vektoru (nebo toho podobného), když můžou destruktory házet. Už když destruktory házet nemůžou to není úplně triviální věc.

JSH

Re:C++ a výjimka v destruktoru
« Odpověď #56 kdy: 05. 02. 2014, 21:38:01 »
A tak všichni používají třeba string i tam, kde by stačilo třeba const char *. Jenže to není podle mantry, takže je to evil. Hnusi se mi tenhle masový styl.
Pointer na char taky není nějaká hitparáda. Na rozdíl od stringu v sobě nemá délku, takže je ho třeba opakovaně procházet znak po znaku nebo tu délku předávat nezávisle. To není úplně šikovné. Navíc pokud si ho chci uložit, tak v případě pointeru musím alokovat a kopírovat. V případě stringu to je jeden inkrement(libstdc++, nevím jak jinde). Ten masový styl občas překvapí.

Re:C++ a výjimka v destruktoru
« Odpověď #57 kdy: 05. 02. 2014, 21:45:47 »
Škoda že nejspíš nikdy neuvidím zdrojáky té LightSpeed knihovny. Zajímalo by mě, jak je tam řešená realokace vektoru (nebo toho podobného), když můžou destruktory házet. Už když destruktory házet nemůžou to není úplně triviální věc.

To je easy.
Realokace se řeší stejně jako v STL, rezervuje se vždycky nějaký kus paměti navíc, kam se pole rožšiřuje. Když už není kam vkládat, alokuje se kus prázdné paměti a pak se všechny prvky přesunou do nového místa. K tomu se používá operace LightSpeed::moveObject, který lze pro každý typ objektu předefinovat. Výchozí implementace je pro C++11 použití move konstruktoru, pro starší verze jako série konstrukce objektu na novém mistě copy constructorem a pak zavolání destruktoru na starém místě.

Pokud dojde při operace move k výjimce ... může dojít i v případě, že se objekt přenáší nějak speciálně. Považuje se objekt, který se přesouval za nepřesunutý. Pokud je přenos realizován jako constructor-destructor, pak je tam ve výjimce v destructoru rollback jako zpětný přenos na původní místo. Jakmile dojde k výjimce při přesunu, všechny prvky doposud přesunuté se musí přesunout zpět na původní místo. Následně se dealokuje paměť a vyjímka se vyhodí ven.

Pokud dojde k výjimce při všech rollback operací, tak je to double exception fault. Během rollback operací vrací funkce uncaught_exception true, takže každý další destruktor ví, že v tu chvíli by už neměl házet další výjimky.

Re:C++ a výjimka v destruktoru
« Odpověď #58 kdy: 05. 02. 2014, 21:52:29 »
A tak všichni používají třeba string i tam, kde by stačilo třeba const char *. Jenže to není podle mantry, takže je to evil. Hnusi se mi tenhle masový styl.
Pointer na char taky není nějaká hitparáda. Na rozdíl od stringu v sobě nemá délku, takže je ho třeba opakovaně procházet znak po znaku nebo tu délku předávat nezávisle. To není úplně šikovné. Navíc pokud si ho chci uložit, tak v případě pointeru musím alokovat a kopírovat. V případě stringu to je jeden inkrement(libstdc++, nevím jak jinde). Ten masový styl občas překvapí.

FYO reference counting u STL řetězců je pokud vím zakázaný, nebo aspoň silně nedoporučovaný.

místo const char * mám ConstStrA a ConstStrW. Fungují přesně tak jak píšete. Mají pointer a délku. Dál ty objekty umí třeba metody find, nebo substr. Drtivá většina funkci přijímají jako řetězec tento typ. Můj standardní string má samozřejmě konverzi na ConstStrX, a pochopitelně mám konverzi i na std::string. Hlavní výhodou je, že se s tím pracuje naprosto stejně jako s řetězcem, jen se to nikdy nikam nekopíruje, dokud není vyložene potřeba (třeba k uchování řetězce pro asynchroní operace).

JSH

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

Takže pokud při tom vyletí výjimka, tak vím že jeden objekt nepřežil cestu tam a kdo-ví-kolik jich zařvalo při tom rollbacku. Takže vlastně o obsahu toho vektoru nevím vůbec nic. No hlavně že je to rychlé. ;D