Warum wird ein pointer nicht genullt wenn man das zugehörige Objekt löscht?
-
Hallo
Ich schreibe eigentlich immer:
delete ptr; ptr = NULL;
Aber wenn Du mal etwas in diesem Forum suchst, wirst Du auch Stimmen finden, die solchen Code schlecht finden. Wenn Du versuchst 2 Mal den selben Pointer zu löschen, ist das fast immer ein logischer Fehler im Programm. Das heißt, Du machst evt. noch einiges andere an solchen Stellen falsch. Da ein delete NULL
aber keinen Fehler liefert, bemerkst Du solche Fehler nicht, wenn Du alle Pointer nach delete auf NULL setzt.
Außerdem könnte es auch sein, dass Du noch die Adresse wissen willst, auf die der Pointer gezeigt hat, auch wenn der Speicherbereich ungültig wird.
Adressberechnungen wieptr2=ptr+4;
sind zwar verpöhnt aber in C++ immer noch erlaubt.
DJohn
-
Ich denk mal, das es inkonsequent waere ....
DU bist halt selbst fuer verantwortlich, finde dich damit ab
und noch 2 sachen ....
1:
char * const pIrgendwas(new char[5]);wie willste denn den loeschen, wenn delete deinen pointer gleich nullen will (damit kann der zeiger selbst nimmer const sein), ausser mit ner zwischenzuweisung ... wobei der const zeiger dann immer noch auf die adresse zeigen wuerd ...
2:
Alle deine funktionen die nen Speicher mittels pointer loeschen durften nur noch mit referenzen oder zeiger auf zeiger arbeiten, damit dein sofortiges loeschen auch durchgereicht wuerde ....Dein aufgezeigter weg ist falsch, aber der bewegrund deiner Gedanken positiv.
Die Loesung:
kapsle deine rohen Zeigen, so dass nur in deiner wrapper-klasse mit dem rohen zeiger in beruehrung kommst ... dann nullst den zeiger auch an zentraler stelle oder auch gar nimmer, weils per logik fehlerfaelle abfasst.In deinen code ausserhalb, wo die benutzung deines Zeigers kritisch ist (du weisst ned ob schon geloescht oder nich, arbeitest mit dem wrapper, der weiss dass dann schon), arbeitest dann mit ner lokalen Instance deines Wrappers ....
Klingt nach viel overhead, kann man aber gschickt durch eigene templates oder smartpointer aus anderen libs minimieren ... und macht vieles sicherer ...
Ciao ...
-
Wer sauber programmiert muss meistens den Zeiger anschließend nicht auf NULL setzen und wenn doch tut man es halt.
Wenn es dich so sehr stört schreib dir ne kleine template-funktion die das tut.Es ist ja verschwendete Rechenzeit und warum sollen sich tausende darüber aufregen nur weil ein paar wenige die Übersicht in ihrem Quellcode verloren haben.
mach einfach ne Funktion, z.B. so:
template<typename T> void ndelete (T* p) { delete p; p = NULL; } //und template<typename T> void ndelete_arr (T[] p) { delete[] p; p = NULL; }
-
Vermutlich, um nicht unnötig Rechenzeit zu verschwenden.
-
Boah, die erste Seite war ja echt ein trauriger Haufen von Nerv-Antworten...
Zur Frage: Weil es Augenwischerei wäre.
int* x = new int; int* y = x; delete x; // und jetzt ist y trotzdem ungültig.
Ich denke nicht, dass Nullsetzen allgemein schlechter Stil ist. Hier wird bestimmt auch doppelt delete aufgerufen:
{ boost::scoped_ptr<int> x(new int); x.reset(); }
Aber der entscheidende Punkt ist, dass man deletes sowieso nicht selbst aufrufen sollte. Mein aktuelles Projekt enthält kein einziges rohes delete, delete[] schon gar nicht (wer braucht new[], seitdem es templates gibt?), und ich hatte nie Memory Leaks oder doppelte deletes. In den mittlerweile 1,5 Jahren hatte ich nur zwei Fehler mit Referenzen in STL-Container, die ungültig wurden und einmal eine Referenz auf eine lokale Variable. Speichermanagement in C++ kann so einfach sein...
Wenn man einen scoped_ptr benutzt, wird der beim Löschen (über delete) automatisch auch genullt. Wenn man mehrere Zeiger auf ein Objekt braucht und auf das Nullen angewiesen ist, kann man shared_ptr und weak_ptr verwenden. Und auch für alle anderen exotischen Fälle erlaubt es einem C++ als einzige Mainstream-Programmiersprache, sich Wrapperklassen ohne geistigen und Laufzeit-Overhead zu schreiben, die das tun, was du in deinem Fall brauchst.
-
VirtualDreams schrieb:
warum willst du's 2 mal löschen????
if(ptr != NULL) { delete ptr; ptr = NULL; }
denke ich mal ohne was falsches gesagt zu haben...
NULL darf gelöscht werden, wer hat diese bescheuerte if-Konstruktion eigentlich erfunden und verbreitet, war das wieder M$?
MfG EIsflamme
-
Wenn ich deine Frage richtig verstanden habe
gehts nur darum, das du gerne
hättest das beim delete alle Zeiger auf diesen Speicher gleich genullt werden.
Das Problem liegt meiner Meinung nach darin, das dann die Speicherverwaltung nicht
nur Buch führen müsste welcher Speicher belegt oder frei ist, sondern auch noch
alle "Referenzen" mitzählen müsste + Verweise auf die entsprechenden Variablen
halten müsste, um diese Aufgaben zu bewältigen. Das würde sicher leicht
ineffektiv.mfg JJ
-
john, kennst du garbage collecting? diese technik wird zb in java benutzt, um speicher freizugeben, auf den keinerlei pointer oder referenzen mehr zeigen. hierbei währe es genau umgekehrt, also kein deutlicher mehraufwand.
und wehe, jetzts agt jemand, dass java lahm sei
-
Ich denke, automatisch genullte Zeiger sind sogar noch um ein paar Größenordnungen einfacher als Garbage Collection... Man braucht nur ne Basisklasse, die Platz für alle Referenzen hat und die im Destruktor auf null setzt, sowie einen Zeiger, der beim Anzeigern und Wegzeigern sich selbst hinzufügt oder löscht. Das Ganze kann man sehr performant implementieren. Bei Interesse kann ich meinen Code gerne mal posten.
-
Ich denke, dass automatisches nullen nach deleten nicht mit automatischer Garbage Collection vergleichbar ist...
Ganz prinzipiell sind das völlig komplett unterschiedliche Ansätze.Was aber am automatischem nullen leichter als an GC sein soll, entzieht sich allerdings meiner Kenntnis. Wenn wir uns jetzt nur auf Speichermanagement beziehen kann es gar nicht leichter gehen als mit nem GC.
Dein automatisches nullen kann solche wunderbaren fehler wie auf ein bereits deallokiertes Objekt zugreifen nicht verhindern. Du hast in jedem Fall undefiniertes Verhalten, ob du jetzt einen nicht-null Zeiger hast und auf ein deallokiertes Objekt zugreifst, oder ob du jetzt einen null-zeiger dereferenzierst. Bei null hast du wenigstens den Vorteil, dass er dir auf einem handelsüblichen Betriebssystem ne acces violation aufdrückt, aber den Fehler hat es nicht verhindert.Der Trick beim GC ist ja, dass du den Fehler nicht machen kannst, etwas zu deallokieren was du noch brauchst. Also nicht wirklich vergleichbar... (ohne damit eine Wertung abgeben zu wollen)
-
Besten Dank Leute, dass hat geholfen