Frage zu starker Exceptionsicherheit



  • pumuckl schrieb:

    Magst du uns die mal zeigen?

    MyClass könnte einen globalen Pointer im Ctor vor dem Werfen setzen.



  • Jockelx schrieb:

    pumuckl schrieb:

    Magst du uns die mal zeigen?

    MyClass könnte einen globalen Pointer im Ctor vor dem Werfen setzen.

    Das würde der starken Exceptionsicherheit aber widersprechen.



  • Jockelx schrieb:

    pumuckl schrieb:

    Magst du uns die mal zeigen?

    MyClass könnte einen globalen Pointer im Ctor vor dem Werfen setzen.

    Und? Dann hätte ich trotzdem noch kein Objekt von MyClass. Die Frage des OT war, ob es verboten ist, das Objekt zu nutzen. Die Antwort ist, dass es kein Objekt gibt, für das es so ein Verbot geben könnte. Da kann der Ctor noch so viele Nebenwirkungen haben. Die Lebenszeit eines Objektes beginnt erst dann, wenn der Ctor regulär verlassen wurde.

    Ethon_notloggedin schrieb:

    Gäbe höchstens die Möglichkeit mit placement-new

    Placement new:

    void pnew()
    {
      void* storage = ::operator new(sizeof(MyClass));
      MyClass* pmc = nullptr;
      try 
      { 
        pmc = new(storage) MyClass(); //placement new
        /* we never get here... */
        pmc->~MyClass();
      }
      catch(...)
      {
        /* pmc is nullptr, because the Ctor threw before the assignment to pmc */ 
        /* storage still points to raw storage, there never was an object constructed in it */
      }
      ::operator delete(storage);
    }
    

    genau das ist übrigens auch der Grund, warum placement new immer mit manuell aufgerufenem Dtor gematcht werden muss. Auch hier gilt: das Objekt hat nie existiert. Auch wenn ggf. (bei nicht-starker Exceptionsicherheit) der Inhalt des rohen Speichers hinter storage geändert wurde oder andere Nebenwirkungen sichtbar werden.



  • pumuckl schrieb:

    Und? Dann hätte ich trotzdem noch kein Objekt von MyClass.

    Warum?
    ~~
    Muss noch ein reinterpret_cast drauf, aber das Objekt ist doch noch da.~~qutatsch
    Es ging doch nur um die Möglichkeit, irgendwie auf das (kaputte) Objekt zuzugreifen oder?

    Wahrscheinlich ist das nicht Standardkonform oder oder so; kA. das interessiert mich bei Sachen, die ich so eh nie machen würde wenig.



  • Jockelx schrieb:

    Es ging doch nur um die Möglichkeit, irgendwie auf das (kaputte) Objekt zuzugreifen oder?

    int main()
    {
      std::string *s;
      std::cout << s->length();
    }
    

    ..



  • Wenn im String-Ctor der Wert auf "Hallo" gesetzt wird, kommt bei dir nicht '5' als Augabe. Von daher nicht vergleichbar.



  • Jockelx schrieb:

    pumuckl schrieb:

    Und? Dann hätte ich trotzdem noch kein Objekt von MyClass.

    Warum?
    ~~
    Muss noch ein reinterpret_cast drauf, aber das Objekt ist doch noch da.~~qutatsch
    Es ging doch nur um die Möglichkeit, irgendwie auf das (kaputte) Objekt zuzugreifen oder?

    Nochmal: ES EXISTIERT KEIN OBJEKT! NICHTMAL EIN KAPUTTES! Wenn der Ctor nicht regulär verlassen wird, hast du vielleicht irgendwelche Nebenwirkungen verursacht, aber es existiert weder das Objekt, noch irgendwelche Teilobjekte. Auch wenn alle Member- und Basisklassen-Konstruktoren durchlaufen worden sind (d.h. wenn die Exception erst im Ctor-Rumpf fliegt), werden dafür auch die Destruktoren aufgerufen, sobald der Ctor mit einer Exception verlassen wird.

    Es gibt folgende 3 Möglichkeiten:

    1. Wenn das Objekt auf dem Stack hätte erzeugt werden sollen (wurde es ja nie), wird durch die Excpetion der Gültigkeitsbereich verlassen -> Der Platz auf dem Stack wird auch gleich mit weggeworfen. Keine Möglichkeit an irgendwas heranzukommen.
    2. Wenn das Objekt auf dem Freispeicher hätte erzeugt werden sollen ( new MyClass() ) wird erst Speicher allokiert, dann der Ctor mit der Exception veröassen und der Speicher sofort wieder deallokiert. -> Kein Speicher, kein Obejkt, keine Möglichkeit an irgendwas ranzukommen.
    3. Wenn das Objekt mit Placement new in irgendwelchem wie auch immer gearteten Speicher hätte erzeugt werden sollen, dann war das roher Speicher. (Ein dort vorher bestehendes Objekt von "class-Type" mit placement new überzubügeln wäre UB). Wenn der Ctor fehlschlägt sind alle Teilobjekte, die dort vielleicht im Rahmen des Ctors vor dem Werfen initialisiert wurden, wieder zerstört. Es bleibt also roher Speicher. Wenn sich das Bitmuster dieses Speichers durch die Ausführung des Ctors geändert haben sollte ist das genauso eine Nebenwirkung wie irgendwelche veränderten globalen Variablen. Das heißt dann aber nur, dass der Ctor nicht die starke Garantie gibt. Das MyClass Objekt hat deshalb trotzdem noch nie existiert.

    Mit irgendwelchen C-Casts oder reinterpret_casts jetzt einen Pointer auf ein MyClass aus dem Hut zu zaubern, bringt nichts. Jeder Zugriff darauf ist UB, egal ob man vorher versucht hat, an der Stelle ein MyClass zu konstruieren oder nicht. Ctor-Exception heißt, das Objekt hat nie existiert. Da gibts keinen Weg drumrum.



  • cooky451 schrieb:

    /* ... */
    

    Du versuchst, auf etwas zuzugreifen, was nicht existiert (und nie existiert hat). Das ist UB.



  • pumuckl schrieb:

    cooky451 schrieb:

    /* ... */
    

    Du versuchst, auf etwas zuzugreifen, was nicht existiert (und nie existiert hat). Das ist UB.

    Ja, echt? Wäre ich nie drauf gekommen..



  • cooky451 schrieb:

    Ja, echt? Wäre ich nie drauf gekommen..

    Mir ist klar, dass du das weißt. Es steht nur in keinem Zusammenhang zu dem, was du zitiert hast oder zur Frage des Threaderstellers.



  • Irgendwie schon. Jockelx versucht irgendwie über einen Pointer auf ein Objekt zuzugreifen, das nie existiert hat. Das Beispiel macht das Gleiche, nur mit weniger drum rum.



  • cooky451 schrieb:

    Jockelx versucht irgendwie über einen Pointer auf ein Objekt zuzugreifen, das nie existiert hat.

    Stimmt.

    cooky451 schrieb:

    Das Beispiel macht das Gleiche, nur mit weniger drum rum.

    Nö. Dein Beispiel macht da ja gar nix; insb. werden auch keine Werte vom Ctor in den Speicher geschrieben.
    Zumindest das macht meine Version ja schon.
    Ist mir aber ziemlich wurscht; wenn Hustbaer da was schöneres auf Lager hat, gerne, wenn nicht, auch egal.
    Das brauch eh kein Mensch, bzw. ich zumindest nicht.



  • cooky451 schrieb:

    Das Beispiel macht das Gleiche, nur mit weniger drum rum.

    Das weniger drumrum, sprich der fehlgeschlagene Ctor-Aufruf ist aber der Kern der Angelegenheit. Dass dein Beispiel UB ist, ist allen klar. Dass die Situation nach einem fehlgeschlagenen Ctor-Aufruf im Prinzip die gleiche ist, weil das Objekt eben nicht existiert, ist der Punkt, den du nicht erwähnt hast. Und genau deshalb ist dein Beispiel für die Frage "Objektzugriff nach Ctor-Exception" erstmal nicht in Zusammenhang gebracht.

    Jockelx schrieb:

    insb. werden auch keine Werte vom Ctor in den Speicher geschrieben.
    Zumindest das macht meine Version ja schon.

    Nur wenn der Ctor die starke Garantie nicht gibt.


Anmelden zum Antworten