Wird der folgende Code Speicherverlust in C ++ verursachen?
class someclass {};
class base
{
int a;
int *pint;
someclass objsomeclass;
someclass* psomeclass;
public:
base()
{
objsomeclass = someclass();
psomeclass = new someclass();
pint = new int();
throw "constructor failed";
a = 43;
}
}
int main()
{
base temp();
}
In dem obigen code, wird der Konstruktor wirft. Die Objekte werden geleckt, und wie können die Speicherverluste vermieden werden?
int main()
{
base *temp = new base();
}
Wie etwa im obigen code? Wie können die Speicherverluste vermieden werden, nachdem der Konstruktor wirft?
InformationsquelleAutor der Frage |
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, es wird ein Speicherleck. Wenn der Konstruktor wirft, kein Destruktor aufgerufen wird (in diesem Fall Sie zeigen nicht einen Destruktor, befreit die dynamisch zugewiesenen Objekte, aber können davon ausgehen Sie hatte eine).
Dies ist ein wichtiger Grund für die Verwendung von smart-Pointer - da der smart poitners sind vollwertige Objekte, Sie erhalten Destruktoren aufgerufen, während der Ausnahme-Stapel entspannen und haben die Möglichkeit, den Speicher frei.
Wenn Sie so etwas wie Boost ' s scoped_ptr<> Vorlage Ihrer Klasse konnte sehen eher aus wie:
Und Sie hätte keine Speicher-Lecks (und die Standard-dtor würde auch bereinigen die dynamische Zuweisung von Arbeitsspeicher).
Zusammenfassend (und hoffentlich auch die Antwort auf die Frage über die
Anweisung):
Wenn eine Ausnahme geworfen wird in einem Konstruktor es gibt mehrere Dinge, die Sie sollten zur Kenntnis nehmen in Bezug auf die ordnungsgemäße Umgang mit Ressourcen bereitgestellt werden, die möglicherweise aufgetreten sind, in die abgebrochene Bau des Objekts:
Dies bedeutet, dass wenn ein Objekt besitzt Ressourcen, die Sie haben 2 Möglichkeiten, um die bereinigen, die Ressourcen, die Sie vielleicht schon erworben wurde, wenn der Konstruktor wirft:
InformationsquelleAutor der Antwort Michael Burr
Beiden neuen werden durchgesickert.
Zuweisen der Adresse des heap-Objekte erstellt, um namens smart-Pointer, so dass es gelöscht wird, innerhalb der intelligente Zeiger Destruktor, get-Aufruf, wenn die exception geworfen wird - (RAII).
Nun psomeclass & pint Destruktoren werden aufgerufen, wenn der Stapel entspannen, wenn die Ausnahme ausgelöst wird, im Konstruktor, und diejenigen, die Destruktoren werden freigeben des allokierten Speichers.
Gewöhnlichen Speicherreservierung mithilfe von (nicht-plcaement) neuen Arbeitsspeichers durch den operator new wird automatisch freigegeben, wenn der Konstruktor eine exception wirft. In Bezug, warum die Mühe zu befreien, die einzelnen Mitglieder (in Reaktion auf die Kommentare zu Mike B ' s Antwort), die automatische Befreiung gilt nur, wenn eine Ausnahme geworfen wird, in der ein Konstruktor, der ein Objekt als neu'ly zugeteilt, nicht in anderen Fällen. Auch der Arbeitsspeicher, der freigegeben wird, ist die für das Objekt reserviert-Mitglieder, nicht alle Speicher, die Sie haben könnten zugewiesenen sagen Konstruktor. d.h. Es würde den Speicher frei, der für die member-Variablen einepintobjsomeclassund psomeclassaber nicht den Speicher von new someclass() und new int().
InformationsquelleAutor der Antwort KTC
Ich glaube, dass die top-Antwort ist falsch und würde immer noch ein Speicherleck.
Der Destruktor für die Klasse Mitglieder nicht werden aufgerufen, wenn der Konstruktor eine exception wirft (weil Sie nie Ihre Initialisierung abgeschlossen, und vielleicht einige Mitglieder haben noch nie erreichten Ihren Konstruktor-Aufrufe).
Die Destruktoren sind nur während der Klasse, die Destruktor-Aufruf. Das macht nur Sinn.
Dieses einfache Programm zeigt es.
Mit der folgenden Ausgabe (mit g++ 4.5.2):
Wenn der Konstruktor fehlschlägt Weg, dann ist es deine Verantwortung, damit umzugehen. Schlimmer noch, die Ausnahme, die ausgelöst werden können von Ihrer Basisklasse' Konstruktor!
Der Umgang mit diesen Fällen ist durch den Einsatz einer "Funktions-try-block" (aber selbst dann müssen Sie vorsichtig-code der Zerstörung Ihrer teilweise initialisiertes Objekt).
Den richtigen Ansatz für dein problem wäre dann so etwas wie dieses:
Wenn Sie es ausführen, Sie erhalten die erwartete Ausgabe, bei der nur die zugewiesenen Objekte sind zerstört und befreit.
Können Sie immer noch arbeiten Sie mit smart shared Pointer, wenn Sie wollen, mit zusätzlichen kopieren. Schreiben Sie einen Konstruktor, ähnlich diesem:
Glück,
Tzvi.
InformationsquelleAutor der Antwort
Schmeissen wenn man in einem Konstruktor, sollten Sie Aufräumen alles, was kam, bevor der Anruf zu werfen. Wenn Sie mit Vererbung zu werfen oder in einem Destruktor, sollten Sie wirklich nicht sein. Das Verhalten ist merkwürdig (nicht mein standard-handy, aber es könnte undefiniert sein?).
InformationsquelleAutor der Antwort hazzen
Ja, dass der code ein Speicherleck. Die Blöcke des Speichers über "neue" werden nicht freigegeben, wenn eine Ausnahme ausgelöst wird. Dies ist ein Teil der motivation hinter RAII.
Zu vermeiden, die Speicherverlust, probieren Sie etwas wie dieses:
InformationsquelleAutor der Antwort John Millikin
Alles, was Sie "neue" muss gelöscht werden, oder Sie werden einen Speicherverlust verursachen. Also diese beiden Zeilen:
Wird Speicherverluste verursachen, weil Sie tun müssen:
In einen finally-block, um Sie zu vermeiden durchgesickert.
Auch, diese Zeile:
Ist unnötig. Sie müssen nur zu tun:
Hinzufügen "= base()" ist überflüssig.
InformationsquelleAutor der Antwort Colen
müssen Sie löschen psomeclass... es ist nicht notwendig, zu bereinigen, die integer...
RWendi
InformationsquelleAutor der Antwort RWendi