Findet ihr es gut das delete bei Null-Pointern definiertes Verhalten hat?



  • Oft hat man aber irgendeinen Zeiger und setzt ihn im Constructor auf 0. Irgendwann später dann wird vielleicht was alloziert und in diesem Pointer gespeichert oder auch nicht. Im destructor schreibt man dann einfach delete, und alles funktioniert so wie es soll.



  • Sir Gossi schrieb:

    In meinen Klassen gibt es Arrays, die nur gelegentlich bereit stehen müssen.

    Dann nimm ein scoped_array, einen vector o.ä. Alles, was mit rohen Zeigern zu tun hat, hat eh schon mehr als genug implizite "Features" - da wäre es mir lieber, sie wären umständlicher (und damit klarer) zu bedienen, weil sie eh gewrappt werden sollten. D.h. klares Ja zur manuellen Null-Abfrage, da sie eh nur in Destruktoren von Wrapperklassen vorkommt.



  • Ach, ich hatte bisher keine Probleme mit meinen temporären Arrays.

    @Delryn: Das mit der Speicheradresse 0000 hat man mir das letzte mal als ich in diesem Forum danach gefragt hab aber noch anders beigebracht.



  • Delryn schrieb:

    Afaik gibts die Speicheradresse 0000, z.B. im rom wo der erste Befehl drinne steht denn sich die cpu holt.

    Natürlich gibts die Adresse. Aber 1) zeigt der Nullpointer nicht zwingend auf die Adresse 0. Das heißt, wenn du z.B. ptr=0 schreibst, ersetzt der Compiler die 0 intern durch die "richtige" Nullpointer-Adresse, so dass du dich in der Praxis nicht mit dieser Umsetzung herumschlagen musst.
    Und 2) heißt es ja nur, dass kein gültiger Zeiger je ein Nullpointer ist. Also wenn dort irgendwelcher ROM-Code steht, passt das doch perfekt, weil weder ein Objekt noch eine Funktion an dieser Stelle stehen kann.



  • liver schrieb:

    Findet ihr das gut? Das versteckt doch nur einen Logikfehler oder nicht? hmm

    es ist voll kacke.
    es untergräbt fast alles, woran ich glaube.
    es versteckt logikfehler. ein assert oder irgend was anderes hartes wäre da im debug-modus angebracht. im release-modes schlich undefiniert. (üblicherweise sehr schnell oder sofort schutzverletzung).
    es ist lahm. ok, nur wenige takte pro delete, aber wenige absolut und vollkommen unnütze takte.



  • Das mit der Geschwindigkeit stimmt, aber new/delete sind von Haus aus sehr langsam (tausende Takte), da fällt das wirklich nicht ins Gewicht.



  • Das hängt doch vom Allokator ab.



  • volkard schrieb:

    liver schrieb:

    Findet ihr das gut? Das versteckt doch nur einen Logikfehler oder nicht? hmm

    es ist voll kacke.

    Ich find's gut, denn ein Nullpointer ist ein schöner Sentinel-Wert den ich recht häufig und gerne verwende. Das man sich explizite if-Abfragen beim Löschen von z.B. optionalen Aggregationen sparen kann macht Code imo einfacher und leichter zu verstehen (anderes Beispiel: Implementation von Move-Operationen). Logikfehler wurden bei mir durch dieses Verhalten bisher nicht versteckt, da ein Nullpointer ja nicht zufällig entsteht. Entweder der Nullpointer hat eine von mir definierte Semantik, dann setze ich Pointer explizit auf 0 (auch mal nach einem delete) und erlaube damit gerne auch mehrfache Aufrufe von delete oder aber, wenn es keine definierte Semantik gibt, setze ich Pointer nicht auf 0 und damit haut's einen bei z.B. Doppel-Deletes schnell raus und Logikfehler werden imo auch nur mit einer äußersts geringen Wahrscheinlichkeit verschleiert.
    Wenn ich auf der anderen Seite Code habe, der von der Annahme ausgeht, dass ein Pointer nicht 0 sein kann (oder darf), dann stelle ich dies über ein explizites Assert sicher. Das hat den Vorteil, dass es a) deutlicher sichtbar ist (nicht versteckt in der Implementation eines Implementationsdetails) und b) den Fehler potentiell früher finden kann (nicht erst beim Löschen).

    Was ich nicht mache und was ich in der Tat für schlecht halte ist die generelle Verwendung von Code wie diesem:

    delete p;
    p = 0;
    

    Mit der Begründung "ich will mich vor Doppel-Deletes" schützen. Das führt dann häufig wirklich zur Verschleierung von Logikfehlern.

    Aber letztlich ist das konkrete Verhalten von delete eh wurscht, solange es explizit und vollständig spezifiziert ist. Wie man hier sieht kann man es eh nie allen Recht machen.



  • Findet ihr es gut das delete bei Null-Pointern definiertes Verhalten hat?

    Ja.

    Findet ihr das gut?

    Ja. 😕

    Das versteckt doch nur einen Logikfehler oder nicht?

    Nein.



  • [quote="HumeSikkins"]Ich find's gut, denn ein Nullpointer ist ein schöner Sentinel-Wert den ich recht häufig und gerne verwende. [quote]
    das ist bedeutungsüberladung.

    Das man sich explizite if-Abfragen beim Löschen von z.B. optionalen Aggregationen sparen kann macht Code imo einfacher und leichter zu verstehen (anderes Beispiel: Implementation von Move-Operationen).

    ich frage gerne der deutlichkeit habler dennoch und überflüssigerweise mit if ab.

    Was ich nicht mache und was ich in der Tat für schlecht halte ist die generelle Verwendung von Code wie diesem:

    delete p;
    p = 0;
    

    Mit der Begründung "ich will mich vor Doppel-Deletes" schützen. Das führt dann häufig wirklich zur Verschleierung von Logikfehlern.

    stimmt.
    aber man baut sich dann ja eh ein void sicherLoesch(T*& t);

    Aber letztlich ist das konkrete Verhalten von delete eh wurscht, solange es explizit und vollständig spezifiziert ist. Wie man hier sieht kann man es eh nie allen Recht machen.

    naja, ich mag halt zero abstraction overhead. mag nicht sachen eingebaut haben, nur weil man es manchmal braucht.
    viele zeiger sind bei mir attribute und sie zeigen sicher auf was (vom ctor sichergestellt).

    es wäre kein problem, wenn delete minimal wäre, also bei delete 0; undefiniert wäre, sich einen smart-pointer zu bauen, der die semantik hat, daß man nen null-zeiger fehlerfrei löschen darf. damit könnte man es beiden seiten recht machen. aber so, wie es jetzt ist, bin ich nicht ganz zufrieden.


Anmelden zum Antworten