Výjimky a dělení nulou
|
3.3.2011 15:08
Miloslav Ponkrác
|
Nejdříve musím předeslat, že článek je vynikající. Ač je pro jinou cílovou skupinu, než jsem já, autor píše skvěle, a precizně.
Jenom na doplnění, ve Windows jsou výjimky součástí celého operačního systému, takže hw i sw problémy vyhazují výjimky automaticky díky operačnímu systému. Jsou to jiné výjimky, tzv. SEH (Structured Exception Hadling), ale dají se konvertovat na C++ výjimky automaticky, nebo zachytávat v C++ blocích, byť mírně jinak. Dělení nulou tedy na Windows vždy vyhodí speciální výjimku.
Ve Windows je schopen už kernel s Vámi komunikovat výjimkami a dává šanci programátorovi ošetřit i stavy i chyby, které by jinak operační systém nemohl nijak řešit a musel byž program násilně ukončit. Ve Windows je programu zaslána výjimka a je na programu, jestli výjimku ošetří a operační systém tedy ví, že program se dostal do stabilního stavu a počítá s tím, nebo neudělá nic a pak výjimka probublá z hlavní funkce programu a operační systém program ukončí, a nebo nabídne programátorovi připojení k debuggeru.
V GCC překladači je možné ve všech platformách ve vlastní funkci terminate použít speciální funkci, která vypíše typ výjimky což se hodí pro ladící účely. |
|
|
Re: Výjimky a dělení nulou
|
4.3.2011 19:47
Aleš Hakl
|
U SEH je potreba zminit to, ze zapnuti automaticke konverze na C++ vyjimky meni ABI. Spolu s faktem, ze ve Windows se pouziva kompilator C++ vicemene na vsechno a C a C++ se prilis nerozlisuje vede na spoustu zajimavych problemu pokud pisete program ktery pouziva pluginy, pripadne pisete plugin do jineho programu (krasny priklad je .pyd do Pythonu). Druhe misto, kde volby kompilatoru ovlivnuji ABI je tchar a okoli, nicmene to by ve slusnem programu nemelo prilis vadit. |
|
|
Re: Výjimky a dělení nulou
|
5.3.2011 12:07
Miloslav Ponkrác
|
Je to úplně jinak. Detaily by zabraly více, než jeden samostatný článek. Pokud uděláte správně knihovnu, Vaše změny zůstanou uvnitř ní. To je problém tvůrce knihoven. Stejně tak bude Python překvapen, když Vám z nějaké knihovny uteče neošetřená C++ výjimka při použití g++. Prostě pokud neumíte udělat pořádně knihovnu, nedělejte to a přenechte to zkušenějším.
Ve Windows se dají SEH výjimky chytat i v C. Ale C se moc nepoužívá, protože není moc důvodů používat C, když existuje C++.
SEH výjimkám ve Windows neunikne nic. Součástí Windows API je i vyhazování SEH výjimek a neexistuje možnost jak to zrušit. Dokonce i kernel drivery mohou dostat výjimku, nebo vyhodit výjimku. SEH výjimku dostane klidně Python program a nezávisle na tom, jak jsou programovány knihovny.
Pokud libovolný program zapisuje třeba na neexistující paměť, Windows kernel to oznámí programu výjimkou a dá šanci programu to napravit a vzpamatovat se z toho. A nebo to ignorovat a pak výjimka probublá ven a Windows program ukončí. Linux na stejný počin zareaguje pouze signálem a bezpodmínečným ukončením programu.
Vyhazování výjimek kernelem má tu výhodu, že výjimku dostane thread, který chybu způsobil a ten je nejlépe kvalifikován chybu napravit, pokud s ní počítá. V unixu prostě proces (náhodný thread) dostane signál a stejně se z řady chyb vůbec nedá vybruslit, protože unix program v řadě případů ukončí proces tak jako tak.
|
|
|
2x uvolněná paměť
|
3.3.2011 18:29
Jaroslav Šmíd
|
Tady pozor...
int *p = new int [100];
try
{
if (myFunction() == false)
throw "Nejaka vyjimka"; delete [] p;
cout << "Pamet uvolnena.\n"; // POZOR!
}
catch (const char *ex)
{
delete [] p;
cerr << "Vyjimka zachycena.\nPamet uvolnena.\n";
}
cout lze nastavit (jako ostatní streamy), aby při chybě vyhodil výjimku s né pouze nastavil chybový příznak streamu. Bude-li toto chování nastaveno a dojde k výjimce zde:
cout << "Pamet uvolnena.\n";
tak se v catch bloku pokusíte znovu uvolnit pointer. Pokud se kombinuje alokování paměti s výjimkami, tak doporučuji použít nějaké "chytré ukazatele", třeba std::shared_ptr, std::auto_ptr, std::unique_ptr, a spol (stačí jenom pro uchování a kvůli rychlosti, pokud je potřebná, pak pracovat přímo s ukazatelem). Taky pozor, že i new operátor může vyhodit std::bad_alloc, takže doporučím i konstrukci
ptr = new(std::nothrow) Objekt;
aby k vyhození výjimky nedocházelo a ručně si ošetřit nulový pointer. |
|
|
Re: 2x uvolněná paměť
|
3.3.2011 22:26
Miloslav Ponkrác
|
Čistě teoreticky lze výjimku dostat kdekoli. Každá funkce, každá metoda může výjimku vyhodit.
Ošetření výjimek by mělo probíhat s nějakým předpokladem. Programátor by si měl přesně určit stav, ve kterém se program nachází po vyhození výjimky. To se museli naučit i standardizátoři C++, kde s tím byly velké boje u STL knihovny. Prvotní verze STL definovala výjimky jednoduše – pokud nastane výjimku uvnitř STL, stav je nedefinovaný. Museli to časem hodně čistit a opravovat.
V reálném případě si programátor buď bude nastavovat do p NULL, aby věděl, zda má uvolňovat. A nebo použije garbage collector, přesněji řečeno princip RAII, kdy si pointer zabalí do třídy, třeba jen do std::auto_ptr a o uvolňování se nestará vůbec. |
|
|
|
|
KOMENTARZE
|
Tylko zarejestrowani użytkownicy mogą dopisywać komentarze.
|
|
Szukanie oprogramowania
|