Výjimky: Uvolnění objektů ve výjimkách
Tento článek vysvětluje potřebu a metodu uvolnění objektů, když dojde k výjimce. Témata:
Výjimky vyvolané architekturou nebo vaší aplikací přeruší normální tok programu. Proto je velmi důležité udržet si přehled o objektech, abyste je mohli správně odstranit v případě, že dojde k výjimce.
Existují dvě primární metody, jak to provést.
Zpracujte výjimky místně pomocí
try
klíčových slov acatch
potom všechny objekty zničíte jedním příkazem.Před vyvolání výjimky mimo blok pro další zpracování zlikvidujte libovolný objekt v
catch
bloku.
Tyto dva přístupy jsou znázorněny níže jako řešení pro následující problematický příklad:
void SomeFunc() // Problematic code
{
CPerson* myPerson = new CPerson;
// Do something that might throw an exception.
myPerson->SomeFunc();
// Now destroy the object before exiting.
// If SomeFunc above throws an exception this code will
// not be reached and myPerson will not be deleted.
delete myPerson;
}
Jak je uvedeno výše, nebude odstraněna, myPerson
pokud je vyvolán SomeFunc
výjimka . Provádění přeskočí přímo na další obslužnou rutinu vnější výjimky, vynechá normální funkci exit a kód, který odstraní objekt. Ukazatel na objekt přejde mimo rozsah, když výjimka opustí funkci a paměť obsazená objektem nebude nikdy obnovena, dokud program běží. Jedná se o nevrácenou paměť; Bylo by zjištěno pomocí diagnostiky paměti.
Místní zpracování výjimky
Paradigma try/catch poskytuje defenzivní programovací metodu pro zabránění nevracení paměti a zajištění toho, aby objekty byly zničeny, když dojde k výjimkám. Příklad uvedený výše v tomto článku se například může přepsat následujícím způsobem:
void SomeFunc()
{
CPerson* myPerson = new CPerson;
try
{
// Do something that might throw an exception.
myPerson->SomeFunc();
}
catch (CException* e)
{
// Handle the exception locally
e->Delete();
}
// Now destroy the object before exiting.
delete myPerson;
}
Tento nový příklad nastaví obslužnou rutinu výjimky tak, aby zachytila výjimku a zpracovávala ji místně. Pak funkci normálně ukončí a zničí objekt. Důležitým aspektem tohoto příkladu je to, že se vytvoří kontext pro zachycení výjimky s bloky try/catch . Bez místního rámce výjimky by funkce nikdy nevěděla, že byla vyvolána výjimka a neměla by možnost normálně opustit a zničit objekt.
Vyvolání výjimek po zničení objektů
Dalším způsobem, jak zpracovat výjimky, je předat je do dalšího vnějšího kontextu zpracování výjimek. catch
V bloku můžete vyčistit místně přidělené objekty a pak vyvolat výjimku pro další zpracování.
Vyvolání funkce může nebo nemusí potřebovat uvolnit objekty haldy. Pokud funkce před vrácením v normálním případě vždy uvolní objekt haldy, měla by funkce před vyvolání výjimky uvolnit také objekt haldy. Na druhou stranu, pokud funkce obvykle neudělí objekt před vrácením v normálním případě, musíte rozhodnout o tom, zda má být objekt haldy uvolněn.
Následující příklad ukazuje, jak lze místně přidělené objekty vyčistit:
void SomeFunc()
{
CPerson* myPerson = new CPerson;
try
{
// Do something that might throw an exception.
myPerson->SomeFunc();
}
catch (CException* e)
{
e->ReportError();
// Destroy the object before passing exception on.
delete myPerson;
// Throw the exception to the next handler.
throw;
}
// On normal exits, destroy the object.
delete myPerson;
}
Mechanismus výjimky automaticky uvolní objekty rámce; Je také volána destruktor objektu rámce.
Pokud voláte funkce, které můžou vyvolat výjimky, můžete použít bloky try/catch , abyste měli jistotu, že zachytíte výjimky a máte šanci zničit všechny objekty, které jste vytvořili. Zejména mějte na paměti, že mnoho funkcí MFC může vyvolat výjimky.
Další informace naleznete v tématu Výjimky: Zachytávání a odstraňování výjimek.