Ist shared_ptr<int> foo(new int(0)) exceptionsicher?



  • Hallo zusammen,

    ich hab mal eine kurze Nachfrage.
    Ist

    shared_ptr<int> foo(new int(0));
    

    exceptionsicher?
    Also nach meiner Interpretation wird für den int Speicher alloziiert und dann für den Reference Counter im shared_pointer. Wenn die zweite Allocation fehlschlägt, hat man ein Memory leak...

    make_shared macht laut msdn nur eine Speicher-Allokation:
    http://msdn.microsoft.com/en-us/library/ee410595.aspx

    Aber im Bereich Why use this make_shared instead of operator new? steht nichts von zusätzlicher Exceptionsicherheit...

    Ist der Code von oben exceptionsicher?

    Gruß,
    XSpille



  • Wenn der ctor eine Exception wirft, ruft er vorher delete auf den übergebenen Zeiger auf. Ich hab jetzt kein Chapter&Verse, es erscheint mir nur logisch und kurzes Googeln durch die boost-Doku zeigt mir, dass ich vermutlich recht habe.



  • XSpille schrieb:

    ich hab mal eine kurze Nachfrage. Ist

    shared_ptr<int> foo(new int(0));
    

    exceptionsicher?

    Ja. Wenn da irgend eine Ausnahme bei fliegt (im Konstruktor von shared_ptr), dann wird der Heap-allozierte int hier garantiert gelöscht. Habe ich eben gerade nachgeguckt (§20.7.2.2.1 [util.smartptr.shared.const])

    Außer der Performanz (nur eine Allozierung statt zwei) bietet make_shared aber trotzdem eine höhere Ausnahmesicherheit.

    void func(shared_ptr<foo>, shared_ptr<bar>);
    
    int main() {
      // schlecht, nicht Ausnahme-sicher
      func(shared_ptr<foo>(new foo),shared_ptr<bar>(new bar));
      // Warum? Weil die einzelnen Zeiger nicht sofort den
      // shared_ptrs übergeben werden müssen. Die Reihenfolge
      // bei dem, was hier passiert, ist unspezifiziert. Bevor
      // der erste Zeiger dem ersten shared_ptr übergeben wird
      // könnte schon der zweite new-Ausdruck ausgeführt werden,
      // welcher mit einer Ausnahme abbrechen könnte ==>
      // Speicherleck
    
      // Die Lösung:
      func(make_shared<foo>(), make_shared<bar>());
    
      // Alternativ:
      shared_ptr<foo> pf (new foo);
      shared_ptr<bar> pb (new bar);
      func(pf,pb);
    }
    


  • krümelkacker schrieb:

    Außer der Performanz (nur eine Allozierung statt zwei) bietet make_shared aber trotzdem eine höhere Ausnahmesicherheit.

    void func(shared_ptr<foo>, shared_ptr<bar>);
    
    int main() {
      // schlecht, nicht Ausnahme-sicher
      func(shared_ptr<foo>(new foo),shared_ptr<bar>(new bar));
      // Warum? Weil die einzelnen Zeiger nicht sofort den
      // shared_ptrs übergeben werden müssen. Die Reihenfolge
      // bei dem, was hier passiert, ist unspezifiziert. Bevor
      // der erste Zeiger dem ersten shared_ptr übergeben wird
      // könnte schon der zweite new-Ausdruck ausgeführt werden,
      // welcher mit einer Ausnahme abbrechen könnte ==>
      // Speicherleck
    
      // Die Lösung:
      func(make_shared<foo>(), make_shared<bar>());
    
      // Alternativ:
      shared_ptr<foo> pf (new foo);
      shared_ptr<bar> pb (new bar);
      func(pf,pb);
    }
    

    Danke krümelkacker! Wie im anderen Thread schon erwähnt, man ist sich dessen manchmal nicht bewußt, obwohl man es eigentlich weiß 👍


Anmelden zum Antworten