C++ a výjimka v destruktoru

Mr. Curious

Re:C++ a výjimka v destruktoru
« Odpověď #120 kdy: 07. 02. 2014, 14:50:40 »
Citace
Sorry ale navrhovat servery s tim, ze kdyz to spadne vyspawnujeme novyho workera neni hodne profesionalna.
Sorry, ale navrhovat server s tím, že crash jednoho threadu mi shodí celý server, není hodné profesionála.
Profesionální programátorovi program nespadne. Nikdy. Program by neměl padat. Na výjimečnou situaci se reaguje výjimkou

A co tohle? http://en.wikipedia.org/wiki/Fail-fast



Sten

Re:C++ a výjimka v destruktoru
« Odpověď #121 kdy: 07. 02. 2014, 15:03:34 »
Těch uživatelů je konečný počet menší nebo roven počtu threadů.

Ale větší nebo roven jedné. A pokud je větší, je určitě lepší, když se jednomu zahlásí 500, než když to celé spadne, ne?

Nic mě nenutí sdílenou pamět mezi workery používat, můžu to udělat, ale nemusím.

Nic kromě sdílení dat mezi workery, jako třeba statistiky nebo nonce pro autorizaci, ale to je maličkost. On to ten Apache asi používá jenom pro parádu ::)

Profesionální programátorovi program nespadne. Nikdy. Program by neměl padat. Na výjimečnou situaci se reaguje výjimkou

A co tohle? http://en.wikipedia.org/wiki/Fail-fast

Sice nesouhlasím s tím, že profesionálnímu programátorovi program nikdy nespadne, může spadnou třeba kvůli kosmickému záření nebo kvůli nějaké komponentě, kterou nemá ten programátor pod kontrolou, ale fail-fast je daleko blíže výjimce než SIGSEGV.

Mr. Curious

Re:C++ a výjimka v destruktoru
« Odpověď #122 kdy: 07. 02. 2014, 15:19:18 »
Sice nesouhlasím s tím, že profesionálnímu programátorovi program nikdy nespadne, může spadnou třeba kvůli kosmickému záření nebo kvůli nějaké komponentě, kterou nemá ten programátor pod kontrolou, ale fail-fast je daleko blíže výjimce než SIGSEGV.

Fail-fast is a property of a system or module with respect to its response to failures. A fail-fast system is designed to immediately report at its interface any failure or condition that is likely to lead to failure. Fail-fast systems are usually designed to stop normal operation rather than attempt to continue a possibly flawed process.

Re:C++ a výjimka v destruktoru
« Odpověď #123 kdy: 07. 02. 2014, 15:24:30 »
Bez pochyby neni sporu o tom, ze vyjimky v destruktoru prinasi vic skody nez uzitku.
To jsou vaše závěry, ne moje

PS: Co takhle udelat nejake hlasovani? 1. otazka: Je to dobre? 2. otazka: chteli byste s takovym kodem pracovat?
OLOL  ;D

Mno a na zaver ...

http://c2.com/cgi/wiki?BewareOfExceptionsInTheDestructor

IMHO ten začátek je legrační
Citace
  • Objects with throwing destructors cannot be used in Standard containers
  • Objects with throwing destructors cannot even be composed safely
  • In the new C++11 standard all throwing destructors terminate the program, even when not UnwindingTheStack

Ad 1) nejdou použít protože to zakázali. Zakázali to, protože nejdou použít... tomu se říká cyklus
Ad 2) [citation needed]
Ad 3) Je obecně špatný krok v normě asi tak jako by vědci prohlásili, že kvantovou fyziku stejně nikdo nechápe, takže ji radši zrušíme.


belzebub

Re:C++ a výjimka v destruktoru
« Odpověď #124 kdy: 07. 02. 2014, 15:44:35 »
"Cleaner, more elegant, and harder to recognize"
Ten článek má tři zásadní chyby:
...

Netvrdim, ze je clanek bezchybny (taky je uz HODNE stary - coz ilustruje zminka o RAII jako o necem neobvyklem), ale me ve sve dobe primel hluboce se zamyslet nad vlastnim konceptem vyjimky, ktera je z principu urcita forma "nelokalniho skoku" a jako takova vnasi do programu skrytou komplexitu, ktera je maskovana za na prvni pohled jednodussi kod, ktery je ovsem roztrousen na mnohem vice mistech. "Hloupe" C-ckove osetrovani navratovych hodnot a odporna hromada if-u pro kazde volani sice neni hezka, ale je LOKALNI - vse je na jednom miste.

Ja vidim pointu v pripade vetsiho projektu, na kterem se podili vetsi mnozstvi ruzne schopnych lidi: pokud pisete v C a otrocky osetrujete kazde volani (a mohou vam to automaticky kontrolovat ruzne nastroje), je celkem trivialni prostym pohledem na cizi (!!) kod jedne funkce/metody zjistit, zda je vse osetreno a behem chvile vite, zda je kod v poradku a nebo neni. V pripade vyjimek to pohledem zjistit nelze, protoze MUSITE odskocit na implementaci kazde volane funkce/metody (je to cizi kod, ktery neznate!!) a overit si co vyhazuje/zachycuje.

Navic jak zde nekolikrat padlo, 100% dodrzovat RAII je TEZKE a kontrolovat dodrzovani RAII v teamu 10+ lidi, pri blizici se deadline je to TEMER NEMOZNE. Toto bych rad zduraznil, protoze to ilustruje cely muj problem c C++. C++ MUZE BYT relativne moderni jazyk (ehm..), bez nebezpecnych pasti a neustalych SEGFAULTu - ale vyzaduje to KAZEN A DISCIPLINU pri psani kodu.
Naproti tomu kod v C, pri dodrizovani KAZNE A DISCIPLINY (a pouziti treba gobject knihovny) muze byt relativne moderni (ehm, ehm, ehm!), bez nebezpecnych pasti a neustalych SEGFAULTu.
Tedy z tohoto pohledu jsou temer EKVIVALETNI (jediny vetsi rozdil je ze kod v c++ je tak o 20-30% kratsi). Jediny PODSTATNY rozdil je pak to, jak dobre je mozne ZARUCIT, ze vsichni clenove teamu budou dodrzovat kazen a disciplinu. A zde C++ prohrava na cele care.

Co jsem tim vsim chtel/nechtel rict: netvrdim ze vyjimky jsou "spatne", ale ze jejich pouzivani ma i svou odvracenou stranu a je dobre byt si vedom toho, ze se jedna o velmi zakerne skrytou komplexitu, ktera se maskuje kratsim a citelnejsim kodem. A TO beru jako hlavni poselstvi toho, dnes jiz ponekud zastaraleho, clanku.


Re:C++ a výjimka v destruktoru
« Odpověď #125 kdy: 07. 02. 2014, 15:56:24 »
Programování obecně vyžaduje kázeň a zejména dodržování různých pravidel a dbát na koncepci a organizaci celého projektu. Platí pro C i pro C++. Chápu, že profesionálové dlouhé léta pracující v C se neradi přeučují na něco jiného. Protože ono se v C++ opravdu programuje úplně jinak. Ale i to vyžaduje kázeň, protože je sice spoustu věcí, které za vás C++ udělá, ale zase je třeba mít o tom přehled, rozumět tomu a vědět co dělám a proč to dělám. Když Cčkař začne kritizovat už jenom třeba fungování obyčejného destruktoru s tím, že nikdy neví přesně, co se uvnitř děje, pak ... já ho celkem chápu ... ale buď musí na sobě pořádně zapracovat, aby se v C++ naučil, a nebo ať to tedy dál matlá v tom Cčku no.

belzebub

Re:C++ a výjimka v destruktoru
« Odpověď #126 kdy: 07. 02. 2014, 16:18:58 »
Programování obecně vyžaduje kázeň a zejména dodržování různých pravidel a dbát na koncepci a organizaci celého projektu. Platí pro C i pro C++. Chápu, že profesionálové dlouhé léta pracující v C se neradi přeučují na něco jiného. Protože ono se v C++ opravdu programuje úplně jinak. Ale i to vyžaduje kázeň, protože je sice spoustu věcí, které za vás C++ udělá, ale zase je třeba mít o tom přehled, rozumět tomu a vědět co dělám a proč to dělám. Když Cčkař začne kritizovat už jenom třeba fungování obyčejného destruktoru s tím, že nikdy neví přesně, co se uvnitř děje, pak ... já ho celkem chápu ... ale buď musí na sobě pořádně zapracovat, aby se v C++ naučil, a nebo ať to tedy dál matlá v tom Cčku no.

Opet jste nepochopil o cem mluvim. V teamu mate 10 lidi, z nich 2-3 jsou "dobri", 3 "prumerni" a zbytek jsou matlalove. To co pisete musi pochopit a dodrzovat jak ti "dobri", tak "matlalove". O tom mluvim.
Rad bych ignoroval Vase narazky na moji schopnost/neschopnost, protoze to nema nic spolecneho s tim o cem mluvim, ale nejsem splachovaci, a proto se musim branit: V C++ delam od r.1993, profesionalne od 1999. Naucil jsem se drive C++, nez C (ne, to neni protimluv - psat udrzovatelne a korektne velky projekt v C je neco jineho nez "nepouzivat tridy a templaty" v C++) a na C jsme presli (cely team) kolem roku 2008. Muzete mi samozrejme neverit, a myslet si, ze je mi 70 a rozciluje me ta dnesni mladez co pise same templaty a objekty, kterym jako geront nerozumim, misto aby pekne vyfiknuli pointerovou aritmetiku, na ktere baziruji protoze to je jedine co umim. Pripadne Vam nabizim jeste alternativu, ze je mi 13 let a kompletne blabolim, protoze umim pouze VisualBasic, nicmene jsem kdesi cetl, ze "v cecku" delaji profici a tak machruji.

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #127 kdy: 07. 02. 2014, 17:02:16 »
Fail-fast is a property of a system or module with respect to its response to failures. A fail-fast system is designed to immediately report at its interface any failure or condition that is likely to lead to failure. Fail-fast systems are usually designed to stop normal operation rather than attempt to continue a possibly flawed process.

Což je přesně to, co dělají výjimky: přeruší výpočet (fail-fast module) a skočí do handleru (next-higher system design level). Všimněte si, že se tam nikde nepíše nic o tom, že má skončit celý program. Kdyby ale měl, opět tu budou řešit výjimky lépe než SIGSEGV. Ten totiž třeba nezaloguje vzniklou chybu a neuklidí sdílené zdroje.

Netvrdim, ze je clanek bezchybny (taky je uz HODNE stary - coz ilustruje zminka o RAII jako o necem neobvyklem), ale me ve sve dobe primel hluboce se zamyslet nad vlastnim konceptem vyjimky, ktera je z principu urcita forma "nelokalniho skoku" a jako takova vnasi do programu skrytou komplexitu, ktera je maskovana za na prvni pohled jednodussi kod, ktery je ovsem roztrousen na mnohem vice mistech. "Hloupe" C-ckove osetrovani navratovych hodnot a odporna hromada if-u pro kazde volani sice neni hezka, ale je LOKALNI - vse je na jednom miste.

RAII je koncept z roku 1994 a je i v ISO C++98. Ten článek je z roku 2005.

Lokální v těch ifech je pouze úklid. A ten v C++ dělají destruktory.

Ja vidim pointu v pripade vetsiho projektu, na kterem se podili vetsi mnozstvi ruzne schopnych lidi: pokud pisete v C a otrocky osetrujete kazde volani (a mohou vam to automaticky kontrolovat ruzne nastroje), je celkem trivialni prostym pohledem na cizi (!!) kod jedne funkce/metody zjistit, zda je vse osetreno a behem chvile vite, zda je kod v poradku a nebo neni. V pripade vyjimek to pohledem zjistit nelze, protoze MUSITE odskocit na implementaci kazde volane funkce/metody (je to cizi kod, ktery neznate!!) a overit si co vyhazuje/zachycuje.

Není. Je naopak velmi obtížné najít, že mezi 15 ify jeden chybí. Nebo že má opačně podmínku. Výjimka má tu výhodu, že se o ně nemusíte starat po cestě, ale pouze tam, kde je vyhozena, a tam, kde je zachycena.

Výjimky by měly být dokumentované, stejně jako by mělo být dokumentované, jestli ta funkce vrací 0 = success (libc konvence) nebo 0 = failure (bool konvence).

Pokud výjimky neznáte, můžete je pořád chytat pomocí catch (const std::exception &e) nebo catch (...).

Navic jak zde nekolikrat padlo, 100% dodrzovat RAII je TEZKE a kontrolovat dodrzovani RAII v teamu 10+ lidi, pri blizici se deadline je to TEMER NEMOZNE. Toto bych rad zduraznil, protoze to ilustruje cely muj problem c C++. C++ MUZE BYT relativne moderni jazyk (ehm..), bez nebezpecnych pasti a neustalych SEGFAULTu - ale vyzaduje to KAZEN A DISCIPLINU pri psani kodu.
Naproti tomu kod v C, pri dodrizovani KAZNE A DISCIPLINY (a pouziti treba gobject knihovny) muze byt relativne moderni (ehm, ehm, ehm!), bez nebezpecnych pasti a neustalych SEGFAULTu.
Tedy z tohoto pohledu jsou temer EKVIVALETNI (jediny vetsi rozdil je ze kod v c++ je tak o 20-30% kratsi). Jediny PODSTATNY rozdil je pak to, jak dobre je mozne ZARUCIT, ze vsichni clenove teamu budou dodrzovat kazen a disciplinu. A zde C++ prohrava na cele care.

Možná to taky zaznělo, ale není to pravda. Dodržování RAII je naopak velmi snadné: každá alokace zdroje znamená vytvoření objektu a objekt spravující zdroje spravuje maximálně jeden zdroj a nic jiného. Problém jsou spíš programátoři „teď to napíšu takhle, opravím to později“, kteří RAII nedodrží, což je ale to samé, jako když mezi 15 ifů vloží narychlo jeden příkaz bez ifu.

Já mám přesně opačnou zkušenost, a to že raw pointery prohrávají na celé čáře.

Sten

Re:C++ a výjimka v destruktoru
« Odpověď #128 kdy: 07. 02. 2014, 18:11:30 »
Mno a na zaver ...

http://c2.com/cgi/wiki?BewareOfExceptionsInTheDestructor

Citace
  • Objects with throwing destructors cannot be used in Standard containers
  • Objects with throwing destructors cannot even be composed safely
  • In the new C++11 standard all throwing destructors terminate the program, even when not UnwindingTheStack

  • Pravda, ty jsou nothrow
  • Není pravda, pokud dodržujete RAII (jeden objekt = jeden zdroj), tak se to stát nemůže (jediná možnost by byla, že pokud vyhodí destruktor při delete, tak se neprovede dealokoace, ale ISO C++ jasně definuje, že se provede i tak). Pokud RAII nedodržujete, tak máte problém přinejmenším i s výjimkami v konstruktoru (vyhození výjimky v konstruktoru → nevolá se destruktor).
  • Není pravda, můžete destruktor označit nothrow(false)

Následně se tam pokračuje tím, že destruktory by měly dělat pouze rollback, takže nemají proč vyhazovat výjimky. Ano, to je možné paradigma, ale pro otázku házejících destruktorů to zaměňuje důvod a následek.

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #129 kdy: 07. 02. 2014, 23:23:10 »
Nic kromě sdílení dat mezi workery, jako třeba statistiky nebo nonce pro autorizaci, ale to je maličkost. On to ten Apache asi používá jenom pro parádu ::)
Apache umí statistiky i mimo sdílenou pamět (ScoreBoardFile). Nonce autorizaci nemusím používat a když to chci, tak se buď smířím s tím, že se rozhodli pro sdílenou pamět, nebo se podívám po jiném řešení (sdílení dat třeba v memcached a mám to i mezi různými instancemi serverů).

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #130 kdy: 07. 02. 2014, 23:28:21 »
Mimochodem zajímalo by mě, jak se dá s výjimkou v destruktoru vyřešit tohle:
Kód: [Vybrat]
#include <iostream>
#include <stdlib.h>

class A
{
public:
    ~A()
    {
        throw 1;
    }

    void* operator new(size_t n)
    {
        return malloc(n);
    }
   
    void operator delete(void *p)
    {
        if (p != 0) free(p);
    }
};

int main()
{
    try
    {
        A* a = new A;
        delete a;
    }
    catch (const int e)
    {
        std::cout << "exception " << e << std::endl;
    }

    return 0;
}
Ten přetížený operátor delete se totiž při vyhození výjimky vůbec nezavolá, takže to leakuje:
valgrind --leak-check=full ./a.out
==2647== HEAP SUMMARY:
==2647==     in use at exit: 1 bytes in 1 blocks
==2647==   total heap usage: 2 allocs, 1 frees, 133 bytes allocated
==2647==
==2647== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2647==    at 0x4C244E8: malloc (vg_replace_malloc.c:236)
==2647==    by 0x400B5E: main (in a.out)

gamer

Re:C++ a výjimka v destruktoru
« Odpověď #131 kdy: 07. 02. 2014, 23:33:24 »
Ono se to delete dokonce nezavolá ani když není přetížené, což výjimky v destruktoru dělá úplně nepoužitelnými.

Re:C++ a výjimka v destruktoru
« Odpověď #132 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

Re:C++ a výjimka v destruktoru
« Odpověď #133 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

Jakub Galgonek

Re:C++ a výjimka v destruktoru
« Odpověď #134 kdy: 08. 02. 2014, 01:29:01 »
Jak je na tom Visual Studio?
Mám jen verzi 2008. V pondělí mohu zkusit 2010

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