Uitzonderingen: Objecten vrijmaken in uitzonderingen

Opmerking

De Microsoft Foundation Classes-bibliotheek (MFC) wordt nog steeds ondersteund. We voegen echter geen functies meer toe of werken de documentatie bij.

In dit artikel worden de noodzaak en de methode voor het vrijmaken van objecten uitgelegd wanneer er een uitzondering optreedt. Dit zijn een aantal van de onderwerpen:

Uitzonderingen die worden veroorzaakt door het framework of door uw toepassing onderbreken de normale programmastroom. Het is dus erg belangrijk om objecten goed bij te houden, zodat u ze op de juiste manier kunt verwijderen voor het geval er een uitzondering wordt gegenereerd.

Er zijn twee primaire methoden om dit te doen.

  • U kunt uitzonderingen lokaal verwerken met behulp van de try en catch trefwoorden en vervolgens alle objecten met één instructie vernietigen.

  • Vernietig een object in het catch blok voordat u de uitzondering buiten het blok gooit voor verdere verwerking.

Deze twee benaderingen worden hieronder geïllustreerd als oplossingen voor het volgende problematische voorbeeld:

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;
}

Zoals hierboven is geschreven, myPerson wordt deze niet verwijderd als er een uitzondering wordt gegenereerd door SomeFunc. De uitvoering springt rechtstreeks naar de volgende buitenste uitzonderingshandler, waarbij de normale functie-uitvoer en de code die het object verwijdert worden overgeslagen. De aanwijzer naar het object valt buiten het bereik wanneer de uitzondering de functie verlaat en het geheugen dat door het object wordt bezet, wordt nooit hersteld zolang het programma wordt uitgevoerd. Dit is een geheugenlek; deze wordt gedetecteerd met behulp van de diagnostische geheugengegevens.

De uitzondering lokaal verwerken

Het try/catch-paradigma biedt een defensieve programmeermethode om geheugenlekken te voorkomen en ervoor te zorgen dat uw objecten worden vernietigd wanneer er uitzonderingen optreden. Het voorbeeld dat eerder in dit artikel wordt weergegeven, kan bijvoorbeeld als volgt worden herschreven:

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;
}

In dit nieuwe voorbeeld wordt een uitzonderingshandler ingesteld om de uitzondering te ondervangen en deze lokaal af te handelen. Vervolgens wordt de functie normaal afgesloten en wordt het object vernietigd. Het belangrijkste aspect van dit voorbeeld is dat er een context wordt gecreëerd om de uitzondering op te vangen met de try/catch-blokken. Zonder een lokaal uitzonderingskader zou de functie nooit weten dat er een uitzondering is opgetreden en niet de kans zou hebben om normaal af te sluiten en het object te vernietigen.

Uitzonderingen genereren na het vernietigen van objecten

Een andere manier om uitzonderingen af te handelen, is door ze door te geven aan de volgende externe context voor het afhandelen van uitzonderingen. In uw catch blok kunt u een aantal lokaal toegewezen objecten opschonen en vervolgens de uitzondering genereren voor verdere verwerking.

De werpende functie hoeft mogelijk geen heap-objecten vrij te geven. Als de functie altijd het heap-object ontlaadt voordat het normaal gesproken retourneert, moet de functie ook het heap-object ontladen voordat de uitzondering wordt opgegooid. Aan de andere kant, als de functie normaal gesproken het object niet vrijgeeft voordat het terugkeert in het normale geval, moet u per geval beslissen of het heap-object moet worden vrijgegeven.

In het volgende voorbeeld ziet u hoe lokaal toegewezen objecten kunnen worden opgeschoond:

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;
}

Met het uitzonderingsmechanisme worden frameobjecten automatisch ongedaan gemaakt; destructor van het frameobject wordt ook wel aangeroepen.

Als u functies aanroept die uitzonderingen kunnen genereren, kunt u try/catch-blokken gebruiken om ervoor te zorgen dat u de uitzonderingen onderscheppen en de kans hebt om objecten te vernietigen die u hebt gemaakt. Houd er met name rekening mee dat veel MFC-functies uitzonderingen kunnen genereren.

Zie Uitzonderingen: Uitzonderingen vangen en verwijderen voor meer informatie.

Zie ook

afhandeling van uitzonderingen