delete Speicherfreigabe



  • also mein Lehrender meinte , man könnte Speicherlecks mit
    der auto_ptr Klasse vermeiden.

    Das ist ja dann eigentlich sinnlos. Weil wenn es zu einem Programmabsturz kommt
    dann gibt ihn ja eh das Betriebssystem frei.



  • Du siehst es nicht richtig, das Problem mit Memory leaks ist nicht wenn kracht. Dann eher egal. Das Problem mit dem Memory Leaks ist ein Programm dass eigentlich ewig laufen soll, aber durch ein leak gezwungen ist, neu zu starten.



  • blurry333 schrieb:

    Das ist ja dann eigentlich sinnlos. Weil wenn es zu einem Programmabsturz kommt
    dann gibt ihn ja eh das Betriebssystem frei.

    Außerdem wird bei 'normalen' Objekten der Destruktor nicht aufgerufen!



  • Hallo blurry333,

    Windows und Linux protokollieren welchem Prozess (Programm) sie welchen (virtuellen) Arbeitsspeicher gegeben haben. Das geschieht Pageweise, z.B. in 4 KB Blöcken.

    Am Ende des Prozesses wird der angeforderte Speicher wieder vom Betriebsystem freigeben.
    Wenn dein Programm zuviel Speicher verbraucht, z.B. indem es nicht mehr benötigten Speicher einfach nicht freigibt, kann das Betriebsystem sich entscheiden die keinen Spiecher mehr zu geben oder einfach dein Programm zu beenden. Das Betriebsystem ist leider stärker ...

    Autopointer lösen das Problem sogenannter memory Leaks nicht wirklich,
    im Grunde ist oft genau das Gegenteil ist der Fall!
    Autopointer verhindern ja gerade die Freigabe von Speicher
    um abzusichern das der Pointer ins Nirvana greift.

    Gruß Frank



  • Frank Erdorf schrieb:

    Autopointer lösen das Problem sogenannter memory Leaks nicht wirklich,
    im Grunde ist oft genau das Gegenteil ist der Fall!
    Autopointer verhindern ja gerade die Freigabe von Speicher
    um abzusichern das der Pointer ins Nirvana greift.

    😕

    In Verbindung mit Exception-Handling können autopointer sehr hilfreich
    sein um memory leaks zu verhindern...



  • Frank Erdorf schrieb:

    Autopointer lösen das Problem sogenannter memory Leaks nicht wirklich,
    im Grunde ist oft genau das Gegenteil ist der Fall!
    Autopointer verhindern ja gerade die Freigabe von Speicher
    um abzusichern das der Pointer ins Nirvana greift.

    Hä? Kannst du das näher erklären?



  • @Athar

    sorry ich hatte shared Pointer im Kopf ...

    Gruß Frank



  • Frank Erdorf schrieb:

    @Athar

    sorry ich hatte shared Pointer im Kopf ...

    Gruß Frank

    Greade Shared Pointer sind als Referenzzähler implementiert und sobald keine Referenzen gibst, zerstört es sich.



  • Frank Erdorf wollte vielleicht darauf hinaus, dass shared_ptr s bei unüberlegtem Einsatz Pseudo-Leaks verursachen können (Speicher, der theoretisch noch freigegeben könnte, aber es aufgrund der Programmlogik nicht wird). Möglicherweise dachte er an zyklische Referenzen.

    Zu sagen, dass shared_ptr aber oft Memory Leaks erzeugt (das Gegenteil von lösen), finde ich jedoch schon etwas übertrieben.



  • Danke, und Sorry für die 'Verwirrung'

    Das Ziel vom shared_ptr ist eben ein anderes,
    es geht nicht darum memory leaks zu verhindern ...
    Das wird aber oft als Feature mit genannt und ist schlichtweg falsch.

    Das delete wird ja nur gemacht wenn keine Refenzen mehr vorhanden sind.
    So ein Ansatz verhindert Zugriffe ins Nirwana, aber keine Memory leaks,
    im Gegenteil.

    Hier braucht es nicht mal zyklische Referenzen,
    es reicht alleine schon die shared_ptr unnötigerweise noch in statischen Objekten, Listen, Maps, ... zu halten.

    Und einen, wie auch immer gearteten Autopointer, nur auf dem Stack liegen zu lassen, ist nicht die Riesen Hilfe, da ist es sowieso übersichtlich.
    Gut bei exceptions wird es einfacher.

    Wer in komplexer Software die memory leaks mal finden musste,
    weiß wovon ich rede.
    Ehrlich: der Zugriff ins Nirwana ist einfacher zu finden ...

    Was soll's Gruß Frank



  • Frank Erdorf schrieb:

    Das Ziel vom shared_ptr ist eben ein anderes,
    es geht nicht darum memory leaks zu verhindern ...
    Das wird aber oft als Feature mit genannt und ist schlichtweg falsch.

    Genau! 👍

    Es gibt einige Programmierer, die shared_ptr für einen GC-Ersatz halten, obwohl man mit ihm primär geteilte Besitzverhältnisse erreicht und ihn auch dementsprechend einsetzen sollte.



  • Frank Erdorf schrieb:

    Und einen, wie auch immer gearteten Autopointer, nur auf dem Stack liegen zu lassen, ist nicht die Riesen Hilfe, da ist es sowieso übersichtlich.
    Gut bei exceptions wird es einfacher.

    Nicht nur bei Exceptions. Du kannst zum Beispiel auch jederzeit ohne Probleme ein return hinsetzen. Du musst nie einen Gedanken ans Aufräumen mehr verschwenden. Hilft auch sehr, wenn erst im nachhinein jemand den Code abändert und dann ein return irgendwo reinsetzt. So muss sich dieser nicht nochmals um irgendwelche Speicherfreigaben kümmern und dann womöglich noch Fehler machen. Da geht es dann aber nicht mehr unbedingt um Smart-Pointer sondern ganz einfach um RAII. Smart-Pointern können dabei helfen das Programm RAII konform zu programmieren.

    Das Smart-Pointer zu Memory-Leaks führen halte ich allerdings für eine etwas gewagte Aussage. Klar ist es möglich, dass jemand die Smart-Pointer für die Ewigkeit speichert, aber wer so unüberlegt programmiert, der hätte auch Memory-Leaks ohne Smart-Pointer generiert. Zudem ist es nicht wirklich ein Memory-Leak, denn ein Memory-Leak verstehe ich so, dass man selber keinen Zeiger mehr auf den Speicher hat und ihn deshalb nicht mehr freigeben kann. Es wäre also eher so, dass das Ressourcen-Management unsauber durchdacht ist.
    Auch ist es nicht die Aufgabe der Smart-Pointer die Freigabe zu verhindern. Es ist nicht die Aufgabe der Smart-Pointer dafür zu sorgen, dass keine Zeiger ins Nirvana zeigen. Smart-Pointer sollen einem nur helfen die Verwaltung der Zeiger zu vereinfachen, bzw. die Freigabe an gewisse Regeln zu koppeln.

    Grüssli



  • Frank Erdorf schrieb:

    es reicht alleine schon die shared_ptr unnötigerweise noch in statischen Objekten, Listen, Maps, ... zu halten.

    Das ist kein Argument. Wenn das der Fall ist, dürfen und sollen die Objekte nicht gelöscht werden. Mit Memory-Leaks hat das wenig zu tun.
    Edit: das fällt bei mir eher unter "Objekte noch nicht löschen, obwohl sie eigentlich nicht mehr gebraucht werden". Ein Memory-Leak ist für mich etwas anderes, wie von Dravere gerade schon beschrieben.



  • Na dann will ich mal wieder BackToTopic und zitiere blurry333

    Das ist ja dann eigentlich sinnlos. Weil wenn es zu einem Programmabsturz kommt dann gibt ihn ja eh das Betriebssystem frei.

    Das ist eine berechtigte Frage, die mittlerweile gut beantwortet wurde.

    So ähnlich sehen das leider auch viele Anwender der shared_ptr:
    Ich brauche mir keine Gedanken zu machen, weil die shared_ptr sich 'automagisch' frei geben, wenn sie nicht mehr benötigt werden.

    Und wenn mein Programm - warum auch immer - mit der Laufzeit ansteigenden Speicherbedarf hat, dann bezeichne ich das als Memory Leak.
    Den Kunden intressiert es wenig das hier auch noch unnütze Referezen auf den Speicher gehalten werden der nicht freigeben wird. Das Resultat ist das gleiche.
    Ob man anwachsenden Speicherbedarf als Memory Leak bezeichnen kann,
    darf jeder für sich selbst entscheiden ...

    Ich persönlich setzte übrigends lieber sogenannte 'Handles' ein.
    Hier kann man den Speicher, anders als beim shared_ptr, ausdrücklich freigeben,
    ohne daß ein anderer, der noch eine Referenz hält, beim Zugriff 'abraucht'.

    Viel Spass noch mit dem Thema,

    Gruß Frank



  • Wenn jemand hirnlos an seine Problemstellung rangeht, kommt dabei Murks raus, völlig gleichgültig, welche Mittel er verwendet. Natürlich begrenzt man die Lebensdauer eines smart pointers so, dass er zerstört wird, wenn er nicht mehr benötigt wird; das ist ja der Sinn der Sache.

    "Ich stelle mir vor, dass Leute das für eine Art magischen Zauberstab halten könnten, der ihnen das Denken abnimmt" halte ich für kein stichhaltiges Argument.

    Übrigens kannst du auch einen shared_ptr explizit resetten:

    std::shared_ptr<int> p = new int(2);
    
    p.reset();
    

Anmelden zum Antworten