Sdílet prostřednictvím


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 a catch 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 SomeFuncvý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.

Viz také

Zpracování výjimek