deleteme - wieso funktioniert das nicht?



  • Ich unterstelle dir, wenn ich der Meinung bin dass du trollst, genau so zu trollen, wie ich es anderen unterstelle, wenn ich der Meinung bin dass sie trollen.

    Wenn dir das nicht passt, dann formuliere deine Fragen so dass man auch davon ausgehen kann dass du es ernst meinst. Was in diesem Thread für mich einfach nicht gegeben ist. Wenn dich das stört, gut, dann erhöhe ich den Leidensdruck bei dir damit vielleicht endlich mal soweit dass du mal darüber nachdenkst.

    Klaro?

    BTW: Ob ich dich nicht leiden kann spielt dabei keine grosse Rolle. Was ich im Übrigen auch so nicht sagen würde. Was im Übrigen jetzt wiederrum eine Unterstellung deinerseits ist. Ist für micht jetzt kein Problem, ich wollte es nur anmerken da du dich im gleichem Atemzug darüber aufregst dass ich dir Dinge unterstelle.

    BTW2: Trollen erfordert im Übrigen keine Absicht. Und wenn du schon selbst zugibst dass du öfters betrunken schreibst und Dinge wie "es ist 3/4 3 und ich einigermaßen betrunken. Geht das als Entschuldigung?" von dir gibst, dann musst du halt damit leben dass behaupte dass du trollst.

    EDIT: Im Übrigen sollte ich nicht SO oft "im Übrigen" im selben Beitrag schreiben wenn ich mich nicht total blamieren will 😞



  • Eigentlich war das Ganze nur eine simple, ernst gemeinte Frage:
    "Kann ein Objekt sich selbst zerstören/ungültig machen?"
    Ich dachte, wenn ich das Objekt nulle müssten auch die Memberfunktionen nicht mehr zugänglich sein, da der Verweis fehlt.

    Daß manche Leute da ne Staatsaffäre draus machen verstehe ich irgendwie nicht. Absolut nicht.



  • Ich nehme an du weisst was UB (undefined behavior) ist? Falls nicht lies es nach.
    Wenn du auf ein Objekt zugreifst das bereits zerstört wurde bekommst du UB.
    UB ist undefined, kann also auch heissen "läuft alles ganz normal als ob das Objekt noch da wäre".
    Wenn du ein Objekt mit memset überschreibst zerstörst du es damit.

    Bei Objekten mit "automatic storage duration" ist das aber problematisch, da so ein Objekt nochmals automatisch zerstört wird. Es wird also der Dtor auf ein Objekt aufgerufen das, da du mit memset drübergebügelt hast, laut Standard bereits als zerstört gilt. Du hast also wieder UB.
    Und zwar mMn. unvermeidlich.
    Man könnte versuchen das Objekt vor dem Ende seines Gültigkeitsbereichs nochmal mit placement new reinzukonstruieren. Aber ob das aus Sicht des Standards dann "OK" ist... weiss nicht. Würde mich nicht darauf verlassen.

    Weiters ist es natürlich ein Fehler ein Objekt mittels memset zu zerstören wenn das korrekte Funktionieren des Programms davon abhängt dass der Dtor aufgerufen wird -- was danach ja nicht mehr erlaubt ist.

    Das selbe gilt für den manuellen Aufruf des Dtors ( this->~T(); wenn ich mich recht erinnere). Auch danach gilt das Objekt als zerstört und darf nicht nochmal zerstört werden.

    Und dass delete auf Objekte mit automatic storage duration nicht erlaubt ist sollte auch klar sein.

    D.h. die einzig sinnvolle Art Objekte mit automatic storage duration zu zerstören ist dafür zu sorgen dass "ihr" Scope verlassen wird. Einen dahingehenden Beitrag hab' ich auch schon geschrieben.
    D.h. die Antwort auf die Frage wie man Objekte mit automatic storage duration korrekt "von innen heraus" zerstört ist: gar nicht, gibt's nicht, geht nicht.
    Als Lösung für Fälle wo man sowas wirklich machen wollen würde fallen mir nur ein:
    * boost::optional o.Ä. verwenden
    * Im Objekt selbst ein "ich wurde zerstört" Flag mitführen
    * Das Objekt doch über [c]new[/c] erzeugen

    EDIT: Unsinn. boost::optional geht nicht "von innen heraus" und bei new hat man ja wieder keine automatic storage duration. Bleibt also nur das Flag. /EDIT

    Ansonsten...

    Bei Objekte die mittels new erzeugt wurden kannst du einfach delete this; sagen.
    Da deine Beispiele aber immer Objekte mit automatic storage duration verwendet haben, ist das wohl nicht die Antwort die du suchst.

    Anm: ich habe jetzt immer "zerstören" geschrieben. Weil ich den Begriff "löschen" für problematisch halte in diesem Zusammenhang. Der manuelle Aufruf des Dtors oder memset zerstören das Objekt, geben aber nicht seinen Speicher frei. delete this; macht dagegen beides.



  • Danke hustbaer, das ist doch endlich mal eine ernsthafte Antwort auf eine ernsthaft gemeinte Frage.


  • Mod

    Man könnte versuchen das Objekt vor dem Ende seines Gültigkeitsbereichs nochmal mit placement new reinzukonstruieren. Aber ob das aus Sicht des Standards dann "OK" ist... weiss nicht. Würde mich nicht darauf verlassen.

    Ist es. Wird gar im Standard demonstriert.


  • Mod

    Hier besteht offenbar immer noch das Missverständnis, dass der Bezeichner eines Objekts irgendwie das Objekt selber wäre. Das ist aber Unsinn, der Bezeichner ist nur eine Hilfe für den Programmierer bei der Erstellung des Programms. Er hat keine Realität im übersetzten Maschinencode. Im laufenden Programm ist das Objekt ein Speicherbereich, der die Memberdaten enthält. Die kann man natürlich auf 0 setzen mit memset (was eventuell undefiniertes Verhalten auslöst, aber egal), dann sind diese Daten eben 0, aber das Objekt existiert an sich noch, bloß seine Werte haben sich geändert. Der Bezeichner existiert nicht mehr zur Laufzeit. Er ist vollständig in der Programmlogik aufgegangen und kann daher nicht zerstört oder überschrieben werden, so dass das Objekt nicht mehr existieren würde. Es gibt keinen Speicherbereich, den man irgendwie überschreiben könnte, um das Objekt vergessen zu machen.

    Das ist so als wolltest du ein Haus abreißen, indem du den Grundriss zerstörst. Die reale Existenz des Hauses hat nichts mehr mit dem Bauplan zu tun und der Bauplan ist auch kein erreichbarer Teil des Hauses.


  • Mod

    Das ist aber Unsinn, der Bezeichner ist nur eine Hilfe für den Programmierer bei der Erstellung des Programms. Er hat keine Realität im übersetzten Maschinencode. [..] Der Bezeichner existiert nicht mehr zur Laufzeit.

    Schon mal was von Linkage gehört? :p

    Die kann man natürlich auf 0 setzen mit memset (was eventuell undefiniertes Verhalten auslöst, aber egal)

    Das tut es nie - data races mal außer Acht gelassen.

    , dann sind diese Daten eben 0, aber das Objekt existiert an sich noch, bloß seine Werte haben sich geändert.

    Es ist möglicherweise irreführend von Werten zu sprechen, auf die du gar nicht zugreifen darfst oder die für die sie enthaltenden Objekte ggf. nicht gültig sind. Die object representation hat sich geändert.

    Das ist so als wolltest du ein Haus abreißen, indem du den Grundriss zerstörst. Die reale Existenz des Hauses hat nichts mehr mit dem Bauplan zu tun und der Bauplan ist auch kein erreichbarer Teil des Hauses.

    Der Bauplan wäre der Typ des Objektes, nicht dessen Name. Du meinst wohl ein Stück Papier dass den Eigentümer benennt </nitpick> 😃



  • SeppJ schrieb:

    Im laufenden Programm ist das Objekt ein Speicherbereich, der die Memberdaten enthält. Die kann man natürlich auf 0 setzen mit memset (was eventuell undefiniertes Verhalten auslöst, aber egal), dann sind diese Daten eben 0, aber das Objekt existiert an sich noch, bloß seine Werte haben sich geändert.

    Das stimmt spätestens dann nicht mehr wenn das Objekt virtuelle Funktionen hat.

    Wenn du in so ner Klasse memset(this, 0, sizeof(*this)) machst, dann ist *this danach kein Objekt dieser Klasse mehr.
    Bzw. es reicht natürlich schon ein *reinterpret_cast<char*>(this) = 0; .
    UB löst du damit aber nicht aus, ausser du greifst danach noch (über this oder sonstwie) auf das Objekt zu.

    Im Standard gibt es dazu einen Paragraphen (weiss die Stelle leider nicht auswendig) der explizit erlaubt Objekte beliebigen Typs mit z.B. einen char* zu überschreiben. Da steht dann auch dass damit das Objekt zerstört wird. Und dass das OK ist, solange das Programm danach eben nicht mehr auf das Objekt zugreift, und das korrekte Verhalten des Programms nicht auf die Ausführung des Dtors angewiesen ist.

    Und die zweite Sache die da mMn. mit reinspielt ist strict aliasing.

    Wenn du z.B. einen POD vollständig mit einem int* überschreibst (was AFAIK auch erlaubt ist, wobei ich mir bei diesem Punkt nicht 100% sicher bin)...
    Dann ist der POD danach kein POD mehr. (Es sei denn er besteht nur aus int Membern, denn dann hast du mit dieser Aktion lediglich strict aliasing-konform auf die Member des PODs zugegriffen.)
    ( int* jetzt deswegen, weil es für [signed/unsigned] char* ja ne strict aliasing Ausnahme gibt -- nen POD mit nem char* zu überschreiben zerstört also den POD nicht. Sonst könnte man PODs ja auch nicht memcpy -en.)

    Daher meine ich es ist OK zu sagen dass man mit memset ein Objekt zerstört. Man verwandelt es in eine Bytewurst. Genau so wie man ein Schnitzel zerstört indem man es durch den Fleishwolf (hihi, Wofl :D) dreht - es ist ja danach kein Schnitzel mehr sondern Faschiertes.


  • Mod

    Ich bin mir ziemlich sicher, dass EOP mit seiner Objektzerstörung aber ganz was anderes meint als eine strikte Standardauslegung zum Thema Gültigkeit des internen Zustands eines Objekts.



  • Ich bin mir ziemlich sicher dass ich mir immer noch nicht sicher bin was EOP überhaupt will bzw. ob er überhaupt irgendwas will.

    So lange er aber nicht genauer beschreibt was es nun wirklich ist was er wissen möchte, ist das meine beste Erklärung die ich ihm geben kann.
    Und da ich EOP zwar als manchmal lästig aber sicher nicht als dumm in Erinnerung habe, denke ich er sollte damit klarkommen.
    Wenn nicht kann er ja nachfragen.



  • Das Ganze war nur eine Schnapsidee. So wie der Selbstzerstörungsknopf bei Raumschiff Enterprise. 😉
    Hat mich dann aber doch interessiert, ob sowas möglich ist.

    Natürlich hätte ich sizeof(*this) statt sizeof(this) nehmen sollen.

    Ich dachte, daß so ein struct wie eine Tabelle mit Verweisen aufgebaut ist.
    Ist anscheinend nicht so.
    Hatte mich nicht tiefergehend damit beschäftigt. War eben nur eine Schnapsidee und ein Schnellschuss. Nix Philosophisches, nix Trolliges war gemeint.



  • Arcoth schrieb:

    SeppJ schrieb:

    Das ist so als wolltest du ein Haus abreißen, indem du den Grundriss zerstörst. Die reale Existenz des Hauses hat nichts mehr mit dem Bauplan zu tun und der Bauplan ist auch kein erreichbarer Teil des Hauses.

    Der Bauplan wäre der Typ des Objektes, nicht dessen Name. Du meinst wohl ein Stück Papier dass den Eigentümer benennt </nitpick> 😃

    Bin auch fast vom Stuhl gefallen. SeppJs Metaphernkanone ist kaputt.

    Vielleicht passt Telefonbucheintrag/Telefon.


  • Mod

    volkard schrieb:

    Arcoth schrieb:

    SeppJ schrieb:

    Das ist so als wolltest du ein Haus abreißen, indem du den Grundriss zerstörst. Die reale Existenz des Hauses hat nichts mehr mit dem Bauplan zu tun und der Bauplan ist auch kein erreichbarer Teil des Hauses.

    Der Bauplan wäre der Typ des Objektes, nicht dessen Name. Du meinst wohl ein Stück Papier dass den Eigentümer benennt </nitpick> 😃

    Bin auch fast vom Stuhl gefallen. SeppJs Metaphernkanone ist kaputt.

    Ja, meine Metapher war anders gemeint. Dann war sie wohl nicht gut, wenn nicht jeder sie auf Anhieb versteht. Das Bauplankonzept ist zu tief mit der Klassenvorstellung verwurzelt, dabei war es hier nicht so gemeint, sondern sollte einen Bezeichner im Programm bedeuten. Etwas, das bei der Planung des Aufbaus hilfreich ist, aber mit der tatsächlichen Existenz eines Dings nichts zu tun hat.

    Vielleicht passt Telefonbucheintrag/Telefon.

    Hatte ich gestern probiert, ist aber leider dank Leprechauns Getrolle mit in der Müllkippe gelandet, weil es mir zu mühsam war, das alles sauber auseinander zu friemeln. Diese Metapher gefällt mir aber auch nicht so ganz, da sie die gleichen Probleme wie Bauplan und Haus hat, nämlich dass der Bauplan prinzipiell in der gleichen Welt wie das Haus existiert. Es ist an sich möglich, den Bauplan oder den Telefonbucheintrag zu ändern. Aber so etwas wie ein Variablenbezeichner ist aus Sicht eines übersetzten Programms eher so etwas wie eine Idee. Ein göttlicher Plan, wenn man so will, der der Struktur des Programms unterliegt, aber selber nicht greifbar ist. In der realen Welt gibt es solch eine strikte Trennung nicht, außer wir werden metaphysisch. Aber wenn man erst einmal ein gesundes Verständnis der Philosophie zum Verständnis braucht, dann hat eine Metapher ihren Zweck verfehlt 😕



  • Ich habe eigentlich nur eine Antwort einer der hauseigenen Koryphäen erwartet:

    Das geht nicht, weil...

    Das daraus eine 6 (wahrscheinlich bald 7) Seiten lange Diskussion wurde überrascht mich jetzt etwas.


Anmelden zum Antworten