"delete" Frage



  • wenn beim new eine Exception fliegt kann das aus zwei Gründen geschehen:

    1. Fehler bei der Speicherallokation. Der Konstruktor des Objektes wird daher nie aufgerufen, alles paletti (außer dass du ohne Speicher schlecht dastehst)

    2. Fehler im Ctor, dann werden die bereits konstruierten Teilobjekte wieder zerstört, die Exception fliegt und auch wieder kein Speicherleck - vorausgesetzt der Ctor ist exceptionsicher implementiert.

    Du kriegst durch ne Exception beim new also keine Speicherlecks
    Von der Exceptionsicherheit her kann man es also eigentlich als Einzeiler machen, wenns sich nur um einparametrige Funktionen handelt. Ob man sich das angewöhnen sollte und dann bei mehrparametrigen Funktionen immer dran denkt, es anders zu machen ist denke ich Geschmackssache. wirklich konsistent wäre es aber wohl nicht.



  • Ok, was heißt das aber nun bei mir? Warum hat hustbaer eine andere Variante empfohlen, die wie sie dem Boost Standard entspricht? Ich meine, wirkliche Probleme sehe ich jetzt nur bei der Übergabe an Funktionen, was aber ist das Problem bei meiner "push_backung"??

    1. Fehler bei der Speicherallokation. Der Konstruktor des Objektes wird daher nie aufgerufen, alles paletti (außer dass du ohne Speicher schlecht dastehst)

    Heißt das also, es kann passieren, das ich einen Null-Pointer in den Vector pushe, wenn dein Fall auftritt, und wird das push_back bei einem nicht-aufruf des Ctors abbgebrochen, wohl eher nicht,ne?



  • die begründung passt nicht auf dein beispiel.

    wie pumuckl schon gesagt und hustbaer es wohl gemeint hat, ist es eine sache der angewöhnung. wenn du es bei deiner einparametrigen funktion so machst, wie hustbaer vorschlägt, wirst du es bei allen anderen funktionen auch eher so machen. konsistenz und gewöhnung, das ist alles.



  • Ahhh alles klar, ok ich hatte gedacht das bezog sich jetzt wirklich spezifisch auf mein Problem. Super dann danke an alle.



  • Since function arguments are evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, and we may never get to the shared_ptr constructor if g throws an exception

    Verstehe ich nicht, die Argumente werden doch gleich komplett ausgewertet und nicht halb das erste, dann halb das zweite, dann die zweite Hälfte vom ersten?
    Dann sehe ich hierbei f( shared_ptr<int>(new int(2)), g() ); irgendwie kein Problem, da bei einer Exception von g() ja der shared_ptr , falls schon konstruiert, einfach destruiert wird. Ist hier evtl der Fall gemeint, dass das new nicht von einem shared_ptr ummantelt ist? Also f( new int(2), g() ); , wobei dann implizit der shared_ptr konstruiert wird?



  • Also so wie ich das verstanden habe, kann es MÖGLICH sein das Funktionsargumente in keiner bestimmten Reihenfolge abgearbeitet werden,und stell dir vor es wird zuerst das 2. Argument abgearbeitet, dort kracht es, dann geht er niemals in das shared_ptr Konstrukt rein.Meine vorstellung der Sache.



  • @Firefighter:

    queer_boy schrieb:

    die begründung passt nicht auf dein beispiel.

    wie pumuckl schon gesagt und hustbaer es wohl gemeint hat, ist es eine sache der angewöhnung. wenn du es bei deiner einparametrigen funktion so machst, wie hustbaer vorschlägt, wirst du es bei allen anderen funktionen auch eher so machen. konsistenz und gewöhnung, das ist alles.

    Genau das.
    Dein Beispiel ist richtig, nur finde ich es besser die Variante vorzuschlagen die auch dann noch funktioniert wenn eine Funktion mehr als nur den shared_ptr als Parameter nimmt. (Deswegen hab ich ja auch "schlecht" und nicht "falsch" geschrieben 😉 )

    Vielleicht wäre es besser gewesen wenn ich gleich erklärt hätte worum es geht 🙂



  • Firefighter schrieb:

    Also so wie ich das verstanden habe, kann es MÖGLICH sein das Funktionsargumente in keiner bestimmten Reihenfolge abgearbeitet werden,und stell dir vor es wird zuerst das 2. Argument abgearbeitet, dort kracht es, dann geht er niemals in das shared_ptr Konstrukt rein.

    Aber ich verstehe nicht, wo dann das Schlechte dabei ist.

    void f(shared_ptr<int>, int);
    int g();
    
    void bad()
    {
        f(shared_ptr<int>(new int(2)), g());
    }
    

    Wenn hier g() zuerst ausgeführt wird und eine Exception fliegt, ist doch alles in Ordnung. Wenn shared_ptr<int>(new int(2)) zuerst ausgeführt wird, dann g() und in g() eine Exception geworfen wird, wird doch der shared_ptr destruiert und kein Speicherleck oder ähnlich Schlimmes passiert. Falls new eine Exception wirft, passiert auch nichts. Wo ist dann das Problem? 😕



  • Das Problem ist, dass new und der Konstruktor von share_ptr nicht gleichzeitig passieren müssen. Sprich, wenn new aufgerufen wird und dann das andere Argument ausgewertet wird und eine exception los lässt, passiert der Konstruktor vom smart Pointer gar nicht und somit hast du ein Memory Leak.



  • Bist du dir sicher, dass das so passieren kann? Ich meine, klar, die Auswertungs-Reihenfolge von Argumenten ist unspezifiziert, aber können die wirklich teilweise und überlappend ausgewertet werden (halb das erste, dann das zweite, dann die zweite Hälfte vom ersten)?



  • Badestrand schrieb:

    Bist du dir sicher, dass das so passieren kann? Ich meine, klar, die Auswertungs-Reihenfolge von Argumenten ist unspezifiziert, aber können die wirklich teilweise und überlappend ausgewertet werden (halb das erste, dann das zweite, dann die zweite Hälfte vom ersten)?

    Ich kann da jetzt nicht mit meinem Namen einstehen, aber Meyers tut es. (Effektive C++ , Tipp 17).
    Aber bei 5.2.2 / 8 kann man mal ansetzen.

    Ich geh jetzt essen. 🙂



  • Badestrand schrieb:

    Bist du dir sicher, dass das so passieren kann? Ich meine, klar, die Auswertungs-Reihenfolge von Argumenten ist unspezifiziert, aber können die wirklich teilweise und überlappend ausgewertet werden (halb das erste, dann das zweite, dann die zweite Hälfte vom ersten)?

    Die Boost-Leute sind sich sicher, und mir reicht das


Anmelden zum Antworten