Memory Leaks - Verständnisfrage



  • Hallo,

    ich hab einmal eine kleine Verständnisfrage zum Thema "Dynamische Speicherverwaltung mit 'new' und 'delete'":
    Wenn wir uns einmal vorstellen, wir hätten eine Basisklasse (Wirbeltiere) und eine abgeleitete Klasse (Hund). Jetzt schreibe ich folgenden Code:

    Wirbeltiere* TierZeiger = new Hund();
    TierZeiger->SetArt("Goldenretriever");
    TierZeiger->SetAlter(2);
    TierZeiger->KontruiereTier();
    delete TierZeiger;
    

    Aber was passiert genau im Speicher? Soweit ich das verstanden habe, wird mit Wirbeltiere TierZeiger = new Hund()* Speicher auf dem Stack für den Zeiger TierZeiger und Speicher auf dem Heap für *TierZeiger reserviert. Nach dem Programmende wird der Destruktor von TierZeiger aufgerufen und damit eliminiert, jedoch nicht der Teil des Zeigers auf dem Heap. Ich muss also dementsprechend auch delete TierZeiger im Code aufführen. Doch was passiert real im Computer wenn ich es nicht tue?
    Und was ist nach dem Programmende mit der Speicheradresse? Ist diese immernoch "kaputt", oder nur zur Laufzeit?

    MFG



  • Kommt drauf an, wie die Klasse Wirbeltiere implementiert ist und ob sie einen virtuellen Destruktor hat.
    Mit virtuellem Destruktor wird automatisch der eigene und der Destruktor der abgeleiteten Klasse aufgerufen, damit wird der Speicher ordnungsgemäß freigegeben (zuerst der Destruktor des abgeleiteten Klassen, anschließend der Destruktor der Basisklasse).
    Ohne virtuellen Destruktor in der Basisklasse wird nur der Destruktor der Basisklasse aufgerufen, was zu Speicherlecks führen kann, aber nicht muss.

    Edit:
    Zumindest gibt nach Prozessende sämtlichen vom Prozess benutzten Speicher und Systemresourcen wieder frei, du klaust dem System also kein RAM nach Prozessende.



  • DocShoe schrieb:

    Kommt drauf an, wie die Klasse Wirbeltiere implementiert ist und ob sie einen virtuellen Destruktor hat.
    Mit virtuellem Destruktor wird automatisch der eigene und der Destruktor der abgeleiteten Klasse aufgerufen, damit wird der Speicher ordnungsgemäß freigegeben (zuerst der Destruktor des abgeleiteten Klassen, anschließend der Destruktor der Basisklasse).
    Ohne virtuellen Destruktor in der Basisklasse wird nur der Destruktor der Basisklasse aufgerufen, was zu Speicherlecks führen kann, aber nicht muss.

    D.h. am besten angewöhnen immer einen virtuellen Destruktor in der Baseclass zu programmieren?

    Edit:

    Okay, also wird das Speicherloch nach dem Programmende (Prozessende) gleich gestopft?



  • Was real passiert, kann man nicht sagen. Da es dem Betriebbsystem oder auch der C++ Runtime überlassen wird. Aber meistens ist es so, das in einer Art Tabelle sich gemerkt wird, wer wo Speicher reserviert/angefordert hat. Und wenn etwas gelöscht wird, wird sich nur in der Tabelle ein Vermerk gemacht bzw. der Eintrag aus der Tabelle genommen.

    Aber der Speicher selbst, der reserviert war, wird nicht "resettet". D.h. du kannst "Goldenretriever" noch im Speicher finden, wenn du einen Speichermonitor bemühst.

    Das ist wie bei der Festplatte: du löschst eine Datei, aber es verschwindet in Wirklichkeit nur der Verzeichniseintrag. Den Inhal der ehemaligen Datei kannst du noch finden.

    Es ist eine Performancefrage.

    Wenn es z.B. um geheime Daten gehen würde, wäre es klüger nicht nur den Eintrag aus der Verwaltung zu nehmen, sondern auch die eigentlichen Daten mit unsinnigen Daten zu überschreiben.


Anmelden zum Antworten