PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : wieso? if(ptr) delete ptr;


mekakic
2011-10-28, 13:50:51
Übersehe ich hier etwas? In C++ Code von Leuten, die eigentlich wissen was sie machen, in zufälligen Beispielen auf Wikipedia, in Tutorials und Bücher, etc. immer wieder begegnet einem diese C++ Codezeile:

SomeClass * ptr = new SomeClass();
//...
if(ptr)
delete ptr;


Die Abfrage nach if(ptr) guckt doch nur auf die Adresse bzw. den Wert, sobald da eine andere Adresse als '0' drin steht, wird das delete aufgerufen. Das sagt doch nicht aus, ob der Speicher wirklich existiert, ich kann in die Pointer ja auch einfach Adresse 0x01 reinstecken. D.h. für alles außer NULL wird delete aufgerufen, aber genau für NULL ist delete auch definiert; der macht dann nur nichts. Alles andere kann die Abfrage aber nicht abfangen... oder übersehe ich hier etwas sehr grundlegendes?

Trap
2011-10-28, 13:58:32
Nö, da gibt es keinen Grund für, das ist einfach Cargo Cult (http://de.wikipedia.org/wiki/Cargo-Kult-Wissenschaft)-programming.

mekakic
2011-10-28, 14:02:15
Der Begriff ist interessant.

Ich hab nie viel mit C gemacht und mich gerade kurz nach dem Schreiben gefragt, ob das vielleicht bei free anders war. War es aber auch nicht... das ist also nichtmal ein historisches Mitschleppen.

del_4901
2011-10-28, 14:12:15
Es kann bei einem custom Allocator Sinn machen, aber eigentlich sollte delete Null Pointer nicht versuchen zu loeschen. Ich habe vor kurzem erst so einen Fall gebraucht, damit der Pointer nicht doppelt geloescht wird. Aber da habe ich auch vor der Allocation den Test gemacht um in einem globalen Pointer etwas Speicher beiseite zu schaffen. Vor dem delete hab ich dann alles schoen geloescht und den globalen Pointer wieder genullt.

Demirug
2011-10-28, 14:12:29
Der Begriff ist interessant.

Ich hab nie viel mit C gemacht und mich gerade kurz nach dem Schreiben gefragt, ob das vielleicht bei free anders war. War es aber auch nicht... das ist also nichtmal ein historisches Mitschleppen.

Doch bei C war es mal früher nicht definiert und so kam es bei einigen C Compiler zu einem Absturz wenn man einen free(NULL) benutzte. IIRC war es ab C89 dann definiert.

Exxtreme
2011-10-28, 14:27:58
Übersehe ich hier etwas? In C++ Code von Leuten, die eigentlich wissen was sie machen, in zufälligen Beispielen auf Wikipedia, in Tutorials und Bücher, etc. immer wieder begegnet einem diese C++ Codezeile:

SomeClass * ptr = new SomeClass();
//...
if(ptr)
delete ptr;


Die Abfrage nach if(ptr) guckt doch nur auf die Adresse bzw. den Wert, sobald da eine andere Adresse als '0' drin steht, wird das delete aufgerufen. Das sagt doch nicht aus, ob der Speicher wirklich existiert, ich kann in die Pointer ja auch einfach Adresse 0x01 reinstecken. D.h. für alles außer NULL wird delete aufgerufen, aber genau für NULL ist delete auch definiert; der macht dann nur nichts. Alles andere kann die Abfrage aber nicht abfangen... oder übersehe ich hier etwas sehr grundlegendes?

Ich glaube nicht, dass es in C++ eine andere Möglichkeit gibt ob der Zeiger existiert oder nicht. Und ist man konsequent indem man Zeiger mit NULL initialisiert dann ist man auf der sicheren Seite.

pest
2011-10-28, 20:20:03
das ist schon sinnvoll z.B.

Eine Klasse die mehrere dynamische Objekte besitzt. Diese werden im Konstruktor auf NULL gesetzt und abhängig von der gegebenen Konfiguration werden einzelne Objekte alloziert.

Der Destruktor muss jetzt nicht jede mögliche Konfiguration überprüfen sondern einfach nur "if (objekt) delete objekt". Mache ich jedenfalls so.

Senior Sanchez
2011-10-28, 22:44:15
das ist schon sinnvoll z.B.

Eine Klasse die mehrere dynamische Objekte besitzt. Diese werden im Konstruktor auf NULL gesetzt und abhängig von der gegebenen Konfiguration werden einzelne Objekte alloziert.

Der Destruktor muss jetzt nicht jede mögliche Konfiguration überprüfen sondern einfach nur "if (objekt) delete objekt". Mache ich jedenfalls so.

Ich glaube, dass es mekakic nicht darum geht.

Aus seiner Frage schließe ich, dass er die zusätzliche Abfrage auf != NULL als redundant ansieht. Denn wenn der pointer wirklich NULL (also 0) als Zieladresse hat, so sollte in modernen Compilern das delete auch so clever sein und versuchen, nicht diesen Speicher an Adresse 0 zu löschen.

Das man Pointer immer ordentlich auf NULL initialisieren sollte, ist ihm denke ich auch bewusst. Er wollte halt nur die Intention hinter diesem Konstrukt wissen.

Exxtreme
2011-10-28, 23:21:41
Aus seiner Frage schließe ich, dass er die zusätzliche Abfrage auf != NULL als redundant ansieht. Denn wenn der pointer wirklich NULL (also 0) als Zieladresse hat, so sollte in modernen Compilern das delete auch so clever sein und versuchen, nicht diesen Speicher an Adresse 0 zu löschen.


Es geht nicht darum, ob der Compiler das erkennt oder nicht. Es geht darum Memoryleaks zu vermeiden. Ein delete ptr; ist schnell vergessen. Viele Programmierer löschen deshalb alle Zeiger ganz am Ende zur Sicherheit nochmal. Und da Compiler hier Terz machen können wenn ein freigegebener Zeiger nochmal freigegeben wird, kommt die Abfrage auf NULL.

del_4901
2011-10-29, 00:23:13
Es geht nicht darum, ob der Compiler das erkennt oder nicht. Es geht darum Memoryleaks zu vermeiden. Ein delete ptr; ist schnell vergessen. Viele Programmierer löschen deshalb alle Zeiger ganz am Ende zur Sicherheit nochmal. Und da Compiler hier Terz machen können wenn ein freigegebener Zeiger nochmal freigegeben wird, kommt die Abfrage auf NULL.
1. Der Compiler macht keinen Terz, das macht dann die Runtime.
2. delete loescht keine Nullzeicher ein zweites mal, das wird einfach ignoriert
- Ausnahme, man hat sein eigenes delete und haelt sich nicht an gaengige Standarts

Trap
2011-10-29, 01:11:06
Und da Compiler hier Terz machen können wenn ein freigegebener Zeiger nochmal freigegeben wird, kommt die Abfrage auf NULL.
Das funktioniert nicht, da delete die Pointer nicht auf NULL setzt. Das muss man schon selber machen.

Wenn man die Pointer aber auf NULL setzt, darf man dann auf den Pointern auch wieder direkt delete aufrufen ohne nutzlosem if davor.

Gast
2011-10-31, 02:04:40
so sollte in modernen Compilern das delete auch so clever sein und versuchen, nicht diesen Speicher an Adresse 0 zu löschen.Das sowieso nicht. Der Nullpointer ist in C nicht als Zeiger auf die Adresse 0 definiert, sondern hat eine besondere Bedeutung. Ein C-Implementierung, die in Kontakt mit einem Nullpointer auch nur daran denkt irgendwas mit der Adresse 0 zu machen, ist meinem Verständnis nach auf keinen Fall korrekt.. Für C++ dürfte das gleiche gelten.

Dr.Doom
2011-10-31, 09:03:42
so sollte in modernen Compilern das delete auch so clever sein und versuchen, nicht diesen Speicher an Adresse 0 zu löschen.
Kann ja auch sein, dass der geschriebene Code auch mal mit nicht moderne Compilern übersetzt werden soll.

Es gibt Situationen, in denen man Code nutzen muss, der auf x Jahre alten Rechnerkonfigurationen übersetzt werden muss. Und da kann ein heute geschriebener Code schonmal Dinge enthalten müssen, die bei einem modernen Compiler nicht mehr nötig sind.

Aber ob das nun beim obigen konkreten Fall so ist, weiss ich leider gerade nicht. :tongue:

Ectoplasma
2011-11-01, 16:47:39
War delete nicht sowieso schon immer so definiert, dass der Aufruf von delete auf einen Null Pointer erlaubt war? Wüsste nicht, dass das jemals anders war. Also ist die vorherige Abfrage auch sinnlos.

Gast
2011-11-01, 19:27:07
1.) Rein vom Programmierstil ist dies sicher die korrekte Version.
If ptr!=null deutet drauf hin, dass ptr an dieser Stelle auch schon null sein könnte, und man diesen Fall bei zukünftigen Erweiterungen mitbedenken sollte (z.B. wenn man eine .Close Methode aufrufen will). Steht diese Zeile nicht dort, so hat der Programmierer vorhergesehen, dass ptr an dieser Stelle nicht null sein sollte.
Ich mache es z.B. in .NET Sprachen auch so, dass ich Variablen mit 0 bzw. null initialisiere, wenn dies für den späteren Programmteil wichtig ist, nur um darauf hinzuweisen, obwohl dies eigentlich schon von sich aus passieren würde.

2.) Möglicherweise ist an der Stelle auch vorher noch irgendeine weitere Anweisung gestanden, bei der es sehr wohl wichtig war, dass man auf null überprüft wie z.B. der Aufruf der Close Methode.

3.) Vielleicht hat der Author auch nur nicht die Zeit bzw. Lust gehabt, sich mit solchen Fragen stundenlang zu beschäftigen, wie delete definiert ist bzw. ob das auch jeder weiß, der den Code liest und ist im Zweifelsfall auf Nummer sicher gegangen. Wenn es gerade keine nennenswerten Performanceprobleme oder unlesbaren Code mit sich bringt schadet es nie, Dinge doppelt zu überprüfen.

Coda
2011-11-01, 20:16:37
War delete nicht sowieso schon immer so definiert, dass der Aufruf von delete auf einen Null Pointer erlaubt war?
Doch, war es schon immer. Ich geh auch davon aus, dass der Compiler das rausoptimiert.