2

Angenommen, wir haben eine Klasse wie folgt aus:Klasse Zeiger Mitglieder und Ausnahmebehandlung

class A { 
    public: 
     A(); 
     ~A(); 
     void foo(); 
     int* pointer; 
}; 

A::A() { 
    pointer = new int; 
} 

A::~A() { 
    delete pointer; 
} 

A::foo() { 
    throw "error"; 
} 

Und die folgenden Beispiele, die es nutzen:

Beispiel 1

int main() { 
    A a; 
    throw "error"; 

    return 0; 
} 

Beispiel 2

int main() { 
    A a; 
    a.foo(); 

    return 0; 
} 

In diesen beiden Fällen wird es ein Speicherverlust, da der Destruktor für A wird niemals aufgrund der nicht behandelte Ausnahme aufgerufen werden.

Meine Frage ist, ob die Verantwortung liegt beim Benutzer der Klasse, um sicherzustellen, dass der Destruktor durch die Behandlung der Ausnahme aufgerufen wird: im ersten Beispiel ist die Ausnahme nicht mit der Klasse verbunden, so würde ich annehmen, dass die Verantwortung liegt der Benutzer der Klasse, aber im zweiten Beispiel wirft die Klasse selbst den Fehler auf - ob der Benutzer der Klasse immer noch sicher ist, dass die Exception korrekt behandelt wird, oder ist das einfach ein schlechtes Design der Klasse selbst?

Antwort

3
void throw(); 

Dies wird nicht kompilieren. throw ist ein reserviertes Schlüsselwort.

Wenn Sie dieses Detail für einen Moment ignorieren, ist Ihre ursprüngliche Annahme nicht ganz richtig.

In diesem Fall wird die Ausnahme nicht abgefangen und das Programm wird beendet, so dass das Speicherleck akademisch ist.

Wenn jedoch ein try/catch-Block im Geltungsbereich vorhanden ist, wird die Ausnahme abgefangen. In beiden Fällen tritt kein Speicherverlust auf. Das Objekt a wurde in beiden Beispielen vollständig konstruiert. Als solche wird eine geworfene Ausnahme a zerstören und ihren Destruktor aufrufen.

Eine ausgelöste Ausnahme wird den Stapel auflösen, bis die Ausnahme abgefangen wird, und als Teil dieses Prozesses alle Objekte im lokalen Bereich zerstören, bis die Ausnahme abgefangen wird.

Also, das ist ein strittiger Punkt. Es gibt kein Speicherleck, vorausgesetzt, dass die Ausnahme eventuell abgefangen wird und niemand sich um irgendetwas kümmern muss.

Die Klasse, die Sie gezeigt haben, ist größtenteils kompatibel mit dem RAII-Prinzip (benötigt einen Kopierkonstruktor und einen Zuweisungsoperator, um die losen Enden abzuschließen). Die einzige Sache, für die die Klasse verantwortlich ist, wäre, wenn eine Ausnahme im Konstruktor ausgelöst wird, was auch immer der Konstruktor zugewiesen hat, muss bereinigt werden.

+0

Ja, das ist wahr, kleine Verbesserungen hinzugefügt. –

+0

Der Leerwurf wurde behoben(); Error. Danke für das Aufzeigen :) – p0llard

1

Das ist ziemlich irrelevant. Der einzige Grund, warum es ein "Speicherleck" gibt, liegt daran, dass das Programm beendet wird, was den Speicher sowieso aufräumt.

Es ist nicht das Problem der Klasse, wenn das Programm in jedem Fall aufgrund einer unbehandelten Ausnahme beendet wird. Stellen Sie sich vor, Sie hätten 100 Klassen, die alle darauf achten müssten, ob eine Funktion (main) Ausnahmen verarbeiten kann.

Verwandte Themen