Ausnahmen: Freigeben von Objekten in Ausnahmen
In diesem Artikel werden die Notwendigkeit und die Methode zum Freigeben von Objekten erläutert, wenn eine Ausnahme auftritt. Dabei werden folgende Themen behandelt:
Ausnahmen, die vom Framework oder von Ihrer Anwendung ausgelöst werden, unterbrechen den normalen Programmablauf. Daher ist es sehr wichtig, die Nahverfolgung von Objekten zu behalten, damit Sie sie ordnungsgemäß löschen können, falls eine Ausnahme ausgelöst wird.
Hierfür gibt es zwei primäre Methoden.
Behandeln Sie Ausnahmen lokal mithilfe der
try
undcatch
Schlüsselwort (keyword)s, und zerstören Sie dann alle Objekte mit einer Anweisung.Zerstören Sie alle Objekte im
catch
Block, bevor Sie die Ausnahme außerhalb des Blocks zur weiteren Behandlung auslösen.
Diese beiden Ansätze werden unten als Lösungen für das folgende problematische Beispiel veranschaulicht:
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;
}
Wie oben beschrieben, wird nicht gelöscht, myPerson
wenn eine Ausnahme ausgelöst wird.SomeFunc
Die Ausführung springt direkt zum nächsten äußeren Ausnahmehandler, wobei der normale Funktionsende umgangen wird, und der Code, der das Objekt löscht. Der Zeiger auf das Objekt geht außerhalb des Gültigkeitsbereichs, wenn die Ausnahme die Funktion verlässt, und der vom Objekt belegte Speicher wird nie wiederhergestellt, solange das Programm ausgeführt wird. Dies ist ein Speicherverlust; sie wird mithilfe des Speichers Diagnose erkannt.
Lokales Behandeln der Ausnahme
Das Try/Catch-Paradigma bietet eine defensive Programmierungsmethode, um Speicherverluste zu vermeiden und sicherzustellen, dass Ihre Objekte zerstört werden, wenn Ausnahmen auftreten. Beispielsweise könnte das weiter oben in diesem Artikel gezeigte Beispiel wie folgt umgeschrieben werden:
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 diesem neuen Beispiel wird ein Ausnahmehandler eingerichtet, um die Ausnahme abzufangen und lokal zu behandeln. Anschließend wird die Funktion normal beendet und das Objekt zerstört. Der wichtige Aspekt dieses Beispiels besteht darin, dass ein Kontext zum Abfangen der Ausnahme mit den Try/Catch-Blöcken erstellt wird. Ohne einen lokalen Ausnahmeframe würde die Funktion niemals wissen, dass eine Ausnahme ausgelöst wurde und nicht die Möglichkeit hätte, normal zu beenden und das Objekt zu zerstören.
Auslösen von Ausnahmen nach dem Zerstören von Objekten
Eine weitere Möglichkeit zum Behandeln von Ausnahmen besteht darin, sie an den nächsten äußeren Ausnahmebehandlungskontext zu übergeben. In Ihrem catch
Block können Sie einige sauber up Ihrer lokal zugeordneten Objekte ausführen und dann die Ausnahme für die weitere Verarbeitung auslösen.
Die auslösende Funktion muss möglicherweise Heap-Objekte behandeln oder nicht. Wenn die Funktion das Heap-Objekt immer vor der Rückgabe im Normalfall umgibt, sollte die Funktion auch die Zuordnung des Heapobjekts behandeln, bevor die Ausnahme ausgelöst wird. Wenn die Funktion das Objekt nicht normalerweise vor der Rückgabe im normalen Fall umgibt, müssen Sie auf Fall-für-Fall-Basis entscheiden, ob das Heap-Objekt deallocated werden soll.
Das folgende Beispiel zeigt, wie lokal zugeordnete Objekte sauber werden können:
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;
}
Der Ausnahmemechanismus behandelt automatisch Frameobjekte; der Destruktor des Frameobjekts wird auch aufgerufen.
Wenn Sie Funktionen aufrufen, die Ausnahmen auslösen können, können Sie try/catch-Blöcke verwenden , um sicherzustellen, dass Sie die Ausnahmen abfangen und die Möglichkeit haben, alle von Ihnen erstellten Objekte zu zerstören. Beachten Sie insbesondere, dass viele MFC-Funktionen Ausnahmen auslösen können.
Weitere Informationen finden Sie unter Ausnahmen: Abfangen und Löschen von Ausnahmen.