Eure Erfahrungen mit shared, weak... Pointern



  • Habt ihr schon shared Pointer und Co in größeren Projekten eingesetzt?

    Genau einmal, weil ich Referenzzaehlung fuer Objekte genau einer Klasse brauchte (und zwar aus Performancegruenden). Ansonsten finde ich sie viel zu sehr gehyped.

    new/delete-Problem

    Es gibt kein new/delete-Problem.


  • Administrator

    skyPilot schrieb:

    Habt ihr schon shared Pointer und Co in größeren Projekten eingesetzt?

    Ja. Wobei natürlich die Frage vorhanden ist, was ein grösseres Projekt ist 😉

    skyPilot schrieb:

    Gabs Probleme mit anderen Frameworks oder sonstigem oder hat alles gut funktioniert?

    Es gab genau zwei Probleme:
    - Übernutzung
    - Der Kompiler ist bei einem Vergleich abgestürzt.

    if(mysharedptr != nullptr) // <- hat den Kompiler zum Absturz gebracht
    if(nullptr != mysharedptr) // <- hat funktioniert
    

    Also das Problem war eher geringfügig 😉

    TyRoXx schrieb:

    Die sind doch dazu da, sich vom new/delete-Problem zu befreien.

    Was für ein new/delete-Problem denn? 😕

    Grüssli



  • knivil schrieb:

    Genau einmal, weil ich Referenzzaehlung fuer Objekte genau einer Klasse brauchte (und zwar aus Performancegruenden). Ansonsten finde ich sie viel zu sehr gehyped.

    new/delete-Problem

    Es gibt kein new/delete-Problem.

    Stimmt! Wenn das Programm beendet wird, wird das OS ohnehin allen Speicher freigegeben. Und wer die Doku sorgfältig liest, wird immer wissen, wer für's delete() verantwortlich ist. Und die paar Abstürze wegen mehrfachem delete() machen Braten auch nicht fett. Unsere Kunden finden trotzdem, dass wir echt tolle Software machen. Es gibt kein new/delete-Problem, weil wir alle Helden sind 😉 😉

    Stefan.


  • Administrator

    @DStefan,
    Nur ein Anfänger hat Probleme mit new/delete. Ich persönlich hatte schon lange keine Speicherlecks mehr, keine doppelten delete, die Verantwortung für den Speicher ist immer ganz klar aufgetrennt, nämlich derjenige, welcher den Speicher anfordert, gibt den Speicher auch wieder frei. Ich mag mich nicht an den letzten Absturz wegen eines solchen Fehlers erinnern.

    Und ich verwende boost::shared_ptr kaum! Es ist nur eine Frage des Designs des Programmes und der Erfahrung des Programmierers. Wen jemand boost::shared_ptr verwendet, um seine Defizite in Erfahrung und dem Design des Programmes auszugleichen, dann ist dies so ziemlich der falsche Weg.

    Grüssli



  • Dravere schrieb:

    @DStefan,
    Nur ein Anfänger hat Probleme mit new/delete. Ich persönlich hatte schon lange keine Speicherlecks mehr, keine doppelten delete, die Verantwortung für den Speicher ist immer ganz klar aufgetrennt, nämlich derjenige, welcher den Speicher anfordert, gibt den Speicher auch wieder frei. Ich mag mich nicht an den letzten Absturz wegen eines solchen Fehlers erinnern.

    Und ich verwende boost::shared_ptr kaum! Es ist nur eine Frage des Designs des Programmes und der Erfahrung des Programmierers. Wen jemand boost::shared_ptr verwendet, um seine Defizite in Erfahrung und dem Design des Programmes auszugleichen, dann ist dies so ziemlich der falsche Weg.

    Grüssli

    Sieh an! Ich hatte immer gedacht, es sei genau anders herum: Erfahrene Programmierer verwenden Smart-Pointer, weil sie genau wissen, was sie daran haben.

    Ich brauche keine klare "Auftrennung" der Verantwortung für ein Objekt, weil es automaitsch gelöscht wird, wenn's keiner mehr verwendet. Ich braucht mein Design nicht zu verändern, bloß um sicher zu stellen, das für jedes new() auch bestimmt genau ein delete() erfolgt. Das führt in der Regel zu klarerem Design. Ich brauche mich beim Auftreten von Exceptions nicht darum zu kümmern, dass aller angeforderter Speicher auch in diesem Fall korrekt freigegeben wird.

    Kurz: Ich habe kapiert, was RAII bedeutet. Und ich verschwende keine Zeit damit, mir über Probleme Gedanken zu machen, die fast immer durch Verwendung von Smart Pointern vermieden werden können. Da gib's wichtigeres.

    Stefan.


  • Administrator

    DStefan schrieb:

    Sieh an! Ich hatte immer gedacht, es sei genau anders herum: Erfahrene Programmierer verwenden Smart-Pointer, weil sie genau wissen, was sie daran haben.

    1. Erfahrene Programmierer setzen die Mittel an den Stellen ein, wo sie auch sinnvoll sind. Das heisst im allgemeinen aber nicht, dass man nur noch shared_ptr oder Smart-Pointer verwendet. Das zeugt meistens eher von schlechten Programmierern, welche nicht ausgewogen oder überlegt programmieren.
    2. Ich habe von shared_ptr geredet, dass ist ein himmelweiter Unterschied zu Smart-Pointern. Der Shared-Pointer ist nur einer von vielen verschiedenen Smart-Pointern.

    Für RAII braucht man keinen shared_ptr , sondern meistens wenn schon einen scoped_ptr / auto_ptr oder im zukünftigen Standard den unique_ptr .
    Und wenn ich dich also richtig verstanden habe, dann hast du lieber ein schlechtes Design, dafür eine einfache Handhabung von Speicher? Na gut, ich habe lieber eine gut durchdachte Bibliothek.
    Ein shared_ptr ist meistens gar nicht nötig und bedeutet nur einen unnötigen Overhead. Es ist ja auch sehr typisch für C++, dass man im allgemeinen sowieso kaum Zeiger benötigt und wenn, dann sind sie meistens sehr eng an Klassen oder einem Scope gekapselt. Wodurch sich dann eher ein scoped_ptr anbietet.
    Sonstige Speicherverwaltung wird in C++ auch oft Containern überlassen. Was allerdings auch wieder ein typisches Beispiel ist, wo intern Zeiger verwendet werden, welche an eine Klasse gebunden sind, wodurch shared_ptr unötig ist. Zum Teil ist in solchen Fällen sogar ein scoped_ptr hinderlich. RAII kann aber trotzdem gewährleistet werden, durch das hinzufügen eines eigenen Destruktors.

    Grüssli



  • Habt ihr schon shared Pointer und Co in größeren Projekten eingesetzt? Gabs Probleme mit anderen Frameworks oder sonstigem oder hat alles gut funktioniert?

    Ja ich habe schon in größeren Projekten Erfahrungen damit gemacht.
    Das war übrigens meine erste erwähnenswerte Erfahrung und diese war nicht wirklich erfreulich.

    Wir hatten heftigste Probleme mit Zirkeln, so daß Speicher gar nicht freigegeben wurde. Weiterhin kam es dazu dass Objekte im falschen Thread Context freigegeben wurden. Das Programm hing, stürzte ab, hatte Memory leaks, ...

    Die erste Funktion die ich verwendet habe war mir den Refence Count anzeigen zu lassen.
    Als zweites hatte ich einen ObjectTracer implementiert in den jede kreierte Klasse eingetragen und beim Zertören ausgetragen wurde.
    Schließlich hatte ich etliche Member, Funktionen und Methoden von Shared Pointer auf Weak Pointer umgestellt. Erst dann lief das Programm stabil.

    Fazit ?
    Genau die selben Probleme wie mit normalen Pointer 😉
    Und es kommt nach wie vor auf ein vernünftiges Design und den Programmierer an.

    Gruß Frank



  • DStefan schrieb:

    Dravere schrieb:

    @DStefan,
    Nur ein Anfänger hat Probleme mit new/delete. Ich persönlich hatte schon lange keine Speicherlecks mehr, keine doppelten delete, die Verantwortung für den Speicher ist immer ganz klar aufgetrennt, nämlich derjenige, welcher den Speicher anfordert, gibt den Speicher auch wieder frei. Ich mag mich nicht an den letzten Absturz wegen eines solchen Fehlers erinnern.

    Und ich verwende boost::shared_ptr kaum! Es ist nur eine Frage des Designs des Programmes und der Erfahrung des Programmierers. Wen jemand boost::shared_ptr verwendet, um seine Defizite in Erfahrung und dem Design des Programmes auszugleichen, dann ist dies so ziemlich der falsche Weg.
    Grüssli

    Sieh an! Ich hatte immer gedacht, es sei genau anders herum: Erfahrene Programmierer verwenden Smart-Pointer, weil sie genau wissen, was sie daran haben.

    Würde ich nicht so sagen.
    Ich verwende boost::shared_ptr nie.



  • skyPilot schrieb:

    Habt ihr schon shared Pointer und Co in größeren Projekten eingesetzt? Gabs Probleme mit anderen Frameworks oder sonstigem oder hat alles gut funktioniert?

    Ich habe mit dem shared_ptr recht gute Erfahrungen gemacht, auch wenn es schon richtig ist, das man diesen nicht überall einsetzen sollte. Ein relativ aktuelles Problem wo ich shared_ptr eingesetzt habe ist eine Stelle bei der nicht genau gesagt werden kann wann die Daten zu löschen sind (Und da wüsste ich jetzt keine sauberere Lösung als shared_ptr). shared_ptr sind gut, aber man sollte immer die Kosten (und Fallstricke) berücksichtigen.

    Was ich wiederum recht massiv verwende sind scoped_ptr.



  • shared_ptr<> vermeide ich, wann möglich; die externe Referenzzählung ist selten die beste oder sauberste Lösung. Wenn ich schon automatisches Speichermanagement verwende, dann nach Möglichkeit intrinsische Referenzzählung a la COM.

    auto_ptr<> allerdings kommt bei mir dauernd vor.



  • shared_ptr habe ich sehr selten.
    scoped_ptr benutze ich hingegen recht oft, für RAII und Exceptionsicherheit ist er sehr geeignet.
    auto_ptr hab ich auch ab und zu, allerdings eher bei Factory-Methoden mit automatischer Freigabe.



  • Nexus schrieb:

    shared_ptr habe ich sehr selten.
    scoped_ptr benutze ich hingegen recht oft, für RAII und Exceptionsicherheit ist er sehr geeignet.

    Die habe ich bisher beide nicht eingesetzt. Das liegt aber wohl auch der Art der Anwendungen (hauptsächlich "number chrunching"). Bei scoped_ptr vermisse ich irgendwie eine release()-Funktion, mit der ich den Zeiger "befreien" kann, ohne dass das Objekt gelöscht wird. Mit dem kommenden unique_ptr wird auto_ptr und scoped_ptr dann wohl überflüssig.

    Nexus schrieb:

    auto_ptr hab ich auch ab und zu, allerdings eher bei Factory-Methoden mit automatischer Freigabe.

    Geht mir auch so. Das ist meiner Meinung nach auch eine gute Dokumentationsmöglichkeit über die Besitzverhältnisse im Code selbst. Der Aufrufer weiß dann, dass er selbst für die Verwaltung der Lebenszeit verantwortlich ist.

    Gruß,
    SP



  • Sebastian Pizer schrieb:

    Bei scoped_ptr vermisse ich irgendwie eine release()-Funktion, mit der ich den Zeiger "befreien" kann, ohne dass das Objekt gelöscht wird.

    Du kannst dir ja schnell einen eigenen scoped_ptr basteln, das sollte nicht schwer sein (wenn du es wirklich brauchst).

    Ich habe mir auch mal einen eigenen Smart Pointer geschrieben, der im Gegensatz zu den üblichen Smart Pointers eine Kopiersemantik besitzt (wird der Zeiger kopiert, so wird das Objekt dahinter kopiert). Habe ich zwar noch nie wirklich produktiv eingesetzt, aber zum Beispiel für das Pimpl-Idiom könnte ich mir eine Anwendung vorstellen (damit die Klasse nicht gleich die grossen Drei implementieren muss). Oder generell, um Header-Abhängigkeiten zu verhindern, da bei Zeigern eine Vorwärtsdeklaration ausreicht.



  • Frank Erdorf schrieb:

    Schließlich hatte ich etliche Member, Funktionen und Methoden von Shared Pointer auf Weak Pointer umgestellt. Erst dann lief das Programm stabil.

    Fazit ?
    Genau die selben Probleme wie mit normalen Pointer 😉
    Und es kommt nach wie vor auf ein vernünftiges Design und den Programmierer an.

    Gruß Frank

    Yep, einmal an der falschen Stelle nen shared, statt nem weak Pointer in ner Klasse und schon gabs ein Memleak.


Anmelden zum Antworten