Wenn auf einen Zeiger addiert wird, was kommt dabei heraus, wenn das
Ergebnis kein gültiger Zeiger mehr ist?
Anders gefragt, wie bekommt man heraus, ob es sich bei einem berechneten
Zeiger (auf eine Liste) um einen gültigen handelt?
Gast schrieb:
> Wenn auf einen Zeiger addiert wird, was kommt dabei heraus, wenn das> Ergebnis kein gültiger Zeiger mehr ist?
Je nach System und Ziel des Zeigers z.B. einen bus error oder einen
segmentation fault oder nix.
> Anders gefragt, wie bekommt man heraus, ob es sich bei einem berechneten> Zeiger (auf eine Liste) um einen gültigen handelt?
Gültige Zeiger in einer eigenen Liste führen und Rechnen mit Zeigern
unterlassen.
Stefan B. schrieb:
> Gast schrieb:>>> Wenn auf einen Zeiger addiert wird, was kommt dabei heraus, wenn das>> Ergebnis kein gültiger Zeiger mehr ist?>> Je nach System und Ziel des Zeigers z.B. einen bus error oder einen> segmentation fault oder nix.
Nicht das ich Stefan da jetzt ins Wort fallen möchte.
Aber mit nix meint er:
Irgendeine Zahl, so wie bei jeder anderen Zeigerarithmetik auch. Und
weiters: nix spezielles passiert.
Und er meint damit nicht:
Ein NULL-Pointer (also ein Pointer mit dem Wert 0)
Gast schrieb:
> Ok, dann habe ich das wohl mit einem Zeiger auf einen String> verwechselt, wo eine True/False Prüfung das gewünschte bewirkt.
Ganz sicher nicht. Das hast du noch einmal verwechselt.
Wenn alles was man hat der Zeiger ist, dann kannst du gründsätzlich
durch Inspektion des Wertes nicht feststellen, ob dieser gültig ist
(also auf gültige Daten zeigt) oder nicht.
Daher ist in C bei so etwas
if( ptr )
free( ptr );
bzw. in C++
if( ptr )
delete ptr;
die Abfrage des Pointer-Wertes eine sinnlose Aktion (in 99% aller Fälle)
Bau dein Programm so auf, dass du dir diese Frage gar ncht stellen musst
und du hast mehr Freude an deinem Programm.
Ob ein Zeiger "gueltig" ist, weiss in der Regel nur der Programmierer. C
kann und will keine Kontrollmassnahmen zur Gueltigkeit von Zeigern
ergreifen ("trust the programmer").
Manche Prozessoren koennen erkennen, ob ein Speicherzugriff auf Bereiche
erfolgt, die nicht zum laufenden Programm gehoeren. Meist wird dann ein
Interrupt erzeugt, und das Betriebssystem kann den laufenden Prozess
beenden. Im embedded Bereich ist das aber selten anzutreffen.
> Anders gefragt, wie bekommt man heraus, ob es sich bei einem berechneten> Zeiger (auf eine Liste) um einen gültigen handelt?
Es ist relativ schwer das run-time herauszufinden. Und was ist der Sinn
dieser Uebung? Wenn ein unberechtigter Zugriff erfolgt, dann ist das
Programm schon in einem undefinierten Zustand, in anderen Worten: es ist
ein Bug vorhanden. Dieser buggy Code kann schon lange zuvor ausgefuehrt
worden sein. Der ungueltige Speicherzugriff ist nur das Symptom, nicht
die Ursache deines Problems.
Wenn du den Speicherzugriff debuggen willst, kann es von Vorteil sein,
das Programm auf Linux zu portieren. Wenn ein Speicherzugriffsfehler
passiert, wird das Programm beendet und das System erzeugt ein core
File, wenn erlaubt (ulimit -c unlimited). Ein core File ist ein Abbild
des Speichers zum Zeitpukt des Fehlers. Dann kannst du den Zustand des
Programms mit GDB einsehen.
Valgrind ist ein anderes nuetzliches Tool um unerlaubte Speicherzugriffe
und memory leaks zu ermitteln.
Wenige Tools werden dir helfen, wenn der Zugriff auf einen 'gueltigen'
Speicherbereich faellt (das heisst, ein Bereich auf den dein Programm
berechtigt ist zuzugreifen), der aber mit anderen Variablen belegt ist.
... schrieb:
> Das ist sogar in 100% der Fälle eine sinnlose Aktion, da free und delete> selbst prüfen, ob der Zeiger 0 ist.
Würde ich normalerweise auch sagen.
In dem 1% der Fälle, die ich offen lassen möchte, fallen diejenigen, bei
denen der Pointer in der überwiegenden Mehrheit der Fälle tatsächlich
NULL ist und man dann tatsächlich den Aufruf einer Funktion einsparen
kann. Das Potential für eine derartige 'Optimierung' würde ich aber mit
1% (eher sogar weniger) einschätzen. Aber es mag solche Fälle
tatsächlich geben.
... schrieb:
> Das ist sogar in 100% der Fälle eine sinnlose Aktion, da free und delete> selbst prüfen, ob der Zeiger 0 ist.
...sollten, aber da es nicht alle so machen (nicht alles, wo Posix
konform draufsteht ist es auch) kann das durchaus Sinn machen.
Ich habe mir das angewöhnt, weil ich damit vor Jahren auf einem alten
Solaris auf die Nase gefallen bin...
Bernhard M. schrieb:
> ... schrieb:>> Das ist sogar in 100% der Fälle eine sinnlose Aktion, da free und delete>> selbst prüfen, ob der Zeiger 0 ist.>> ...sollten, aber da es nicht alle so machen (nicht alles, wo Posix> konform draufsteht ist es auch) kann das durchaus Sinn machen.>> Ich habe mir das angewöhnt, weil ich damit vor Jahren auf einem alten> Solaris auf die Nase gefallen bin...
Gut, wenn man den Fall tatsächlich hat, kann man auf die Schnelle
natürlich wenig dagegen tun. Der Compiler bzw. die Runtime Lib hat immer
Recht. Aber letztendlich musst du dir bewusst sein, dass du damit einen
Compiler/Library Bug umgehst, der besser beim Compiler Hersteller gefixt
wird.
Sinnlos ist die Operation trotzdem. Leider denken viele C++
Programmierer, dass sie mit ....
if( Ptr )
delete Ptr
a) auf der sicheren Seite sind. Ihnen also nichts passieren kann, denn
sie haben den Pointer ja auf 'Gültigkeit' geprüft.
b) sie einen wahnsinng cleveren Hack machen um damit Freigaben zu
beschleunigen.
Das genaue Gegenteil ist der Fall :-)
Bernhard M. schrieb:
> ...sollten, aber da es nicht alle so machen (nicht alles, wo Posix> konform draufsteht ist es auch) kann das durchaus Sinn machen.
Das ist nichtmal Posix, das ist C-Standard, und zwar seit Jahren.
Jörg Wunsch schrieb:
> Bernhard M. schrieb:>>> ...sollten, aber da es nicht alle so machen (nicht alles, wo Posix>> konform draufsteht ist es auch) kann das durchaus Sinn machen.>> Das ist nichtmal Posix, das ist C-Standard, und zwar seit Jahren.
Kann sein, daß es das ist; es ist auch richtig, daß es ein Library bug
ist der vom Hersteller gefixed wird, aber ich kann wegen eines solchen
Problems keinnen update einer Library (bzw. Patch) beim Kunden
verlangen...
Ich wollte nur darauf hinweisen, daß allein das Vorhandensein einer
scheinbar sinnlosen Anweisung nicht heisst, das der Entwickler nichts /
das falsche gedacht hat...
Es ist aber eine verbreitete Konvention (und auch der Sinn von NULL im
Sinne der Spracherfinder), einem Zeiger NULL zuzuweisen, solange er auf
nichts sinnvolles zeigt. Daher frag ich mich, warum
1
if(ptr)free(ptr);
falsch ist, solange ich diese Konvention anwende.
Zeiger erst gar nicht prüfen, weil ich micht selbst für einen Idioten
halte und davon ausgehe, dass eh irgendwo ein Bug drin ist, der dafür
sorgt, dass ein Nicht-Nullzeiger auftritt, der auf nichts sinnvolles
zeigt, und ich das ganze eh nicht korrekt hinkrieg, scheint mir eine
nicht sehr sinnvolle Strategie.
Von "falsch" hat niemand was gesagt.
Bernhard M. schrieb:
> Das ist sogar in 100% der Fälle eine sinnlose Aktion, da free und delete> selbst prüfen, ob der Zeiger 0 ist.
Oliver
der mechatroniker schrieb:
> Es ist aber eine verbreitete Konvention (und auch der Sinn von NULL im> Sinne der Spracherfinder), einem Zeiger NULL zuzuweisen, solange er auf> nichts sinnvolles zeigt. Daher frag ich mich, warum>
1
if(ptr)free(ptr);
> falsch ist, solange ich diese Konvention anwende.>
Für C absolut guter Stil! In c++ ist
delete null
allerdings als korrekt definiert und erzeugt keinen Fehler
Gruß
Tom
Thomas Burkhart schrieb:
> Für C absolut guter Stil! In c++ ist
man malloc():
free() frees the memory space pointed to by ptr, which must have been
returned by a previous call to malloc(), calloc() or realloc().
Otherwise, or if free(ptr) has already been called before, undefined
behaviour occurs. If ptr is NULL, no operation is performed.
> delete null>> allerdings als korrekt definiert und erzeugt keinen Fehler
dito.
Natuerlich immer ausgenommen kaputte Implementationen, wie oben ja schon
Jemand ausfuehrte.
Thomas Burkhart schrieb:
> Für C absolut guter Stil! In c++ ist>> delete null>> allerdings als korrekt definiert und erzeugt keinen Fehler
Das gleiche gilt auch für C, also auch dort kein guter Stil, sondern
schlicht überflüssig.
Schon der steinalte ANSI-C Standard sagt:
1
The free function causes the space pointed to by ptr to be
2
deallocated, that is, made available for further allocation.
Thomas Burkhart schrieb:
> Ok, dann war meine Erinnerung da falsch.
Als Entwickler hat man 2 Moeglichkeiten: Man arbeitet als Entwickler auf
Basis von veraltetem Know-How, oder man steckt den ganzen Tag die Nase
in die sich staendig aendernden "Standards" ;-)
Oliver schrieb:
> Von "falsch" hat niemand was gesagt.>> Bernhard M. schrieb:>> Das ist sogar in 100% der Fälle eine sinnlose Aktion, da free und delete>> selbst prüfen, ob der Zeiger 0 ist.>> Oliver
Da hast Du mich falsch zitiert!!! Das kam nicht von mir.... ;-)
der mechatroniker schrieb:
> Daher frag ich mich, warum>
1
if(ptr)free(ptr);
> falsch ist, solange ich diese Konvention anwende.>> Zeiger erst gar nicht prüfen, weil ich micht selbst für einen Idioten> halte und davon ausgehe, dass eh irgendwo ein Bug drin ist, der dafür> sorgt, dass ein Nicht-Nullzeiger auftritt, der auf nichts sinnvolles> zeigt,
Genau dieser Fehler ist aber der Regelfall eines Fehlers an dieser
Stelle. Und die Abfrage kann dich nicht davor schützen.
Ein andere 'Konvention', die man auch ab und an sieht:
some_Type_T * ptr;
ptr = (some_Type_T*)malloc( .... );
also das zurechtcasten des Ergebnisses von malloc.
Tut das nicht, auch wenn man es des Öfteren sieht. Ihr könnt euch damit
einen bösen Fehler verstecken!
(*) wobei man sagen muss, dass es einen Fall gibt. Nämlich den, dass
derselbe Code unverändert durch den C++ Compiler soll. Dann braucht man
den Cast. Allerdings wäre es besser in so einem Fall den Code so
umzuarbeiten, dass er new benutzt. Aber bei einem Einsatz eines C
Compilers ist dieser Cast unnötig und wie die meisten unnötigen Casts
eine potentielle Fehlerquelle.
> Genau dieser Fehler ist aber der Regelfall eines Fehlers an dieser> Stelle. Und die Abfrage kann dich nicht davor schützen.
Was mich davor aber schützt, ist an den kritischen Stellen, an denen der
Zeiger zugewiesen wird, korrekten Code zu schreiben. Ich könnte
natürlich eine zusätzliche Variable einführen, die mir sagt, ob ein
bestimmter Pointer gerade verwendet wird oder nicht. Wenn ich die dann
aber nicht korrekt mitführe, dann schützt mich die Abfrage genausowenig.
Und wenn ich sie korrekt mitführe, dann hab ich eine Variable mehr, was
die Sache nicht übersichtlicher macht.
der mechatroniker schrieb:
>> Genau dieser Fehler ist aber der Regelfall eines Fehlers an dieser>> Stelle. Und die Abfrage kann dich nicht davor schützen.>> Was mich davor aber schützt, ist an den kritischen Stellen, an denen der> Zeiger zugewiesen wird, korrekten Code zu schreiben.
Na ja, das ist ein wenig zu einfach gedacht. Ein Pointer wird ja nicht
von sich aus ungültig. Aber du hast im Grunde schon recht.
Und im Grunde ging es auch nicht darum.
Es ging darum, dass dieses 'Idiom'
if( Ptr )
free( Ptr );
keinen Wert hat. Es schützt vor nichts. Es hilft einem nichts. Es ist
(meistens) noch nicht einmal eine 'Optimierung' in irgendeiner Form. Es
ist genau so gut wie ein simples
free( Ptr );
Es hat die gleichen Probleme, die selben Stolperfallen. Kurz und gut:
Die Abfrage bringt gar nichts. nientje, nada, nothing.
Und trotzdem sieht man sie häufig.
Ausgangspunkt der ganzen Story war ja die Fragestellung des OT
> Anders gefragt, wie bekommt man heraus, ob es sich bei einem> berechneten Zeiger (auf eine Liste) um einen gültigen handelt?
bzw. seine Ergänzung
> Ok, dann habe ich das wohl mit einem Zeiger auf einen String> verwechselt, wo eine True/False Prüfung das gewünschte bewirkt.
Und ich glaube in diesen beiden Sätzen im Prinzip genau dieses
if( Ptr )
free( Ptr );
wiedererkannt zu haben.
"Mach die Abfrage und mir kann nichts passieren."
Wohlgemerkt: Es handelt sich um den Fall, dass er Pointerarithmetik
betreibt und hinterher sicher gehen will, dass der resultierende Pointer
gültig ist. Das ist etwas anderes als eine Dereferenzierung über einen
NULL Pointer. Dort macht es natürlich schon Sinn, sich gegen einen NULL
Pointer zu schützen.
Karl heinz Buchegger schrieb:
> also das zurechtcasten des Ergebnisses von malloc.> Tut das nicht, auch wenn man es des Öfteren sieht. Ihr könnt euch damit> einen bösen Fehler verstecken!
Welchen?
Für alle Funktionen, die nicht vorher deklariert worden sind, nimmt der
Compiler automatisch als return-Typ int an. Wenn man nun das zum malloc
gehörende #include <stdlib.h> vergisst, geht der Comiler auch bei dieser
Funktion davon aus. Das heißt, daß dann der zurückgegebene Zeigerwert
als int interpretiert und dann bei der Zuweisung von int wiederum in
einen Zeiger konvertiert wird. Es gibt zwar Plattformen, auf denen die
Konvertierung auch nur eine Uminterpretation der Bits ist, aber das ist
nicht überall so. Ein gutes Beispiel für eine Plattform, wo das
üblicherweise nicht so ist, ist der PC, wenn auch nur im 64bit-Modus. Da
ist ein Zeiger nämlich doppelt so groß wie ein int und so würde bei der
Zuweisung die Hälfte vom Zeiger abgeschnitten. Der Cast sorgt dafür,
daß der Compiler das auch kommentarlos so akzeptiert. Ohne den Cast muß
der Compiler hier warnen. Mit dem Cast sagst du dem Compiler soviel wie:
"Auch wenn du das für blödsinnig hältst und meinst, mich deshalb warnen
zu müssen: Ich will das so, also halt die Klappe und mach's einfach".
Das ist zwar so richtig, aber durch den cast bleibt malloc()
immer noch undeklariert.
Wenn jemand 1. stdlib.h nicht nimmt und 2. die Warnungen
wegen "implicit declaration" ignoriert, ist ihm eh nicht mehr zu helfen.
Das wäre für mich kein Grund, den cast weg zu lassen.
> Das ist zwar so richtig, aber durch den cast bleibt malloc()> immer noch undeklariert.
Ja, aber dann warnt einen der Compiler.
> Wenn jemand 1. stdlib.h nicht nimmt und 2. die Warnungen> wegen "implicit declaration" ignoriert,
Dazu muß er sie erstmal kriegen. Der Cast sorgt dafür, daß man die
Warnung eben nicht mehr kriegt.
> Das wäre für mich kein Grund, den cast weg zu lassen.
Was heißt "weg zu lassen"? Wozu wurde er überhaupt dazugefügt? Er ist an
dieser Stelle völlig unnötig.
Rolf Magnus schrieb:
>> Das ist zwar so richtig, aber durch den cast bleibt malloc()>> immer noch undeklariert.>> Ja, aber dann warnt einen der Compiler.
Eben.
Der cast hilft nicht vor der Warnung wg. undeklariertem malloc().
>>> Wenn jemand 1. stdlib.h nicht nimmt und 2. die Warnungen>> wegen "implicit declaration" ignoriert,>> Dazu muß er sie erstmal kriegen. Der Cast sorgt dafür, daß man die> Warnung eben nicht mehr kriegt.
Nein.
1
intmain(intnargs,char**args)
2
{
3
4
char*p=(char*)malloc(100);
5
return0;
6
}
liefert bei mir:
1
klaus@a64a:~ > gcc -Wall t.c
2
t.c: In function ‘main’:
3
t.c:4: warning: implicit declaration of function ‘malloc’
4
t.c:4: warning: incompatible implicit declaration of built-in function ‘malloc’
5
t.c:4: warning: unused variable ‘p’
>>> Das wäre für mich kein Grund, den cast weg zu lassen.>> Was heißt "weg zu lassen"? Wozu wurde er überhaupt dazugefügt? Er ist an> dieser Stelle völlig unnötig.
Lebensnotwendig ist er sicher nicht.
Aber erstens zeigt es, was man will (für den Leser), zweitens
schreibe ich viel in C++ und habe einen möglichst einheitlichen Stil.
Deshalb schreibe ich hier den cast.
Ohne den Anspruch, da missionieren zu wollen...
Klaus Wachtler schrieb:
> Der cast hilft nicht vor der Warnung wg. undeklariertem malloc().
Darum bin ich wohl noch nie in diese toedliche Falle getappt ;-)
> t.c:4: warning: implicit declaration of function ‘malloc’> t.c:4: warning: incompatible implicit declaration of built-in function> ‘malloc’
Ok, ist bei gcc mittlerweile Standard, weil er das schon eingebaut hat.
War aber nicht immer so und ist nicht bei jedem Compiler so.
>> Was heißt "weg zu lassen"? Wozu wurde er überhaupt dazugefügt? Er ist>> an dieser Stelle völlig unnötig.>> Lebensnotwendig ist er sicher nicht.> Aber erstens zeigt es, was man will (für den Leser),
Inwiefern zeigt ein
1
structfoo*p=malloc(sizeof(structfoo));
das weniger gut als die entsprechende Zeile mit Cast?
> zweitens schreibe ich viel in C++ und habe einen möglichst einheitlichen> Stil.
In C++ brauche ich eigentlich sehr selten einen Cast. Da bestimmt nicht,
weil ich statt malloc dann new verwende. Und wenn mal ein Cast vorkommt,
dann ist es auch kein C-Style-Cast. Daher sehe ich an dieser Stelle
keine Möglichkeit, einen Stil zu vereinheitlichen.
> Ohne den Anspruch, da missionieren zu wollen...
Och komm, wenn schon, denn schon ;-)
Rolf Magnus schrieb:
>> t.c:4: warning: implicit declaration of function ‘malloc’>> t.c:4: warning: incompatible implicit declaration of built-in function>> ‘malloc’>> Ok, ist bei gcc mittlerweile Standard, weil er das schon eingebaut hat.> War aber nicht immer so und ist nicht bei jedem Compiler so.
Gibt es noch andere Compiler?
In den letzten Jahren kam mir ehrlich gesagt nur gcc und MS-VC++
unter die Finger.
>>>> Was heißt "weg zu lassen"? Wozu wurde er überhaupt dazugefügt? Er ist>>> an dieser Stelle völlig unnötig.>>>> Lebensnotwendig ist er sicher nicht.>> Aber erstens zeigt es, was man will (für den Leser),>> Inwiefern zeigt ein>>
1
>structfoo*p=malloc(sizeof(structfoo));
2
>
>> das weniger gut als die entsprechende Zeile mit Cast?
In diesem Beispiel sieht es natürlich auch ein Blinder mit Krückstock.
Aber leicht abgewandelt:
1
structfoo*p=NULL;
2
3
// ...
4
5
// 2 Jahre gehen ins Land, man heiratet, lässt sich scheiden,
6
// und dann kommt ein:
7
p=malloc(sizeof(structfoo));
Mit cast wäre jetzt klarer, was man vorhat.
>>> zweitens schreibe ich viel in C++ und habe einen möglichst einheitlichen>> Stil.>> In C++ brauche ich eigentlich sehr selten einen Cast. Da bestimmt nicht,> weil ich statt malloc dann new verwende. Und wenn mal ein Cast vorkommt,
Für Objekte ja, für Speicher nein.
> dann ist es auch kein C-Style-Cast. Daher sehe ich an dieser Stelle> keine Möglichkeit, einen Stil zu vereinheitlichen.
Doch, wenn man denselben Code mal als C und mal C++ braucht.
>>> Ohne den Anspruch, da missionieren zu wollen...>> Och komm, wenn schon, denn schon ;-)
ok, also:
Ohne cast ist Murks, wer das macht ist doof.
Aber im Ernst: ich behaupte ja nicht, daß der cast da nötig ist
und aus Karl-Theodor Maria Nikolaus Johann Jacob Philipp Franz
Joseph Sylvester Freiherr von und zu Guttenberg einen Mann
des Volkes macht.
Einen guten Grund gegen den cast kann ich allerdings nach wie
vor nicht erkennen.
>> Ok, ist bei gcc mittlerweile Standard, weil er das schon eingebaut hat.>> War aber nicht immer so und ist nicht bei jedem Compiler so.>> Gibt es noch andere Compiler?
Ja, wobei der einzige davon, den ich in letzter Zeit verwendet hab, was
die Meldungen angeht, sowieso völlig unbrauchbar ist. Der scheint nur
eine einzige Fehlermeldung zu kennen, nämlich "Syntax Error", und die
meisten davon meldet er eine Zeile nach Ende der Datei.
> Mit cast wäre jetzt klarer, was man vorhat.
Naja, ich find's auch so klar, aber das ist eben Ansichtssache.
>> In C++ brauche ich eigentlich sehr selten einen Cast. Da bestimmt>> nicht, weil ich statt malloc dann new verwende. Und wenn mal ein Cast>> vorkommt,>> Für Objekte ja, für Speicher nein.
Warum? New wurde absichtlich so gemacht, daß es für beides geht.
"Speicher" ist dann auch nur ein Array aus Objekten vom Typ unsigned
char.
>> dann ist es auch kein C-Style-Cast. Daher sehe ich an dieser Stelle>> keine Möglichkeit, einen Stil zu vereinheitlichen.>> Doch, wenn man denselben Code mal als C und mal C++ braucht.
Wenn ich es als C schreibe, compiliere ich es auch als C. Man kann es ja
immer noch problemlos mit C++-Code zusammenlinken. Nur der Header muß
natürlich passend geschrieben sein.
> Einen guten Grund gegen den cast kann ich allerdings nach wie> vor nicht erkennen.
Naja, mit modernen Compilern schwindet dieser Grund wohl. Ich mache da
trotzdem keinen Cast, weil ich auch keinen Grund dafür erkennen kann.
Klaus Wachtler schrieb:
> Aber leicht abgewandelt:>>
1
>structfoo*p=NULL;
2
>
3
>// ...
4
>
5
>// 2 Jahre gehen ins Land, man heiratet, lässt sich scheiden,
6
>// und dann kommt ein:
7
>p=malloc(sizeof(structfoo));
8
>
>> Mit cast wäre jetzt klarer, was man vorhat.
Mit einem ordentlichen Bezeichner statt "p" ebenfalls. ;-) Einen
Namen wie "i" oder "p" würde ich nur benutzen, wenn das alles
übersichtlich auf eine 24x80-Bildschirmseite passt.
Eine hart "in die Finger verdrahtete" Initialisierung lokaler
Variablen (wie hier das "= NULL") habe ich mir auch abgewöhnt.
Manchmal vertut man sich irgendwo in der Logik und ist der Meinung,
man hätte alle Fälle abgedeckt, da ist die Compilerwarnung "could
possibly be used uninitialized" sehr nützlich, sowas aufzudecken.
Wenn man dagegen "aus Prinzip" überall Initialiserungen vorsieht,
ist für den Compiler immer alles in Butter.
Jörg Wunsch schrieb:
> Einen Namen wie "i" oder "p" würde ich nur benutzen, wenn das alles> übersichtlich auf eine 24x80-Bildschirmseite passt.
Nicht mal dann, zumindest nicht, solange ich noch schneller tippen als
denken kann.
Klaus Wachtler schrieb:
> Aber leicht abgewandelt:>>
1
>structfoo*p=NULL;
2
>
3
>// ...
4
>
5
>// 2 Jahre gehen ins Land, man heiratet, lässt sich scheiden,
6
>// und dann kommt ein:
7
>p=malloc(sizeof(structfoo));
8
>
>> Mit cast wäre jetzt klarer, was man vorhat.
Dem kann ich nicht folgen, inwiefern man da jetzt irgendetwas besser
sieht.
Ich würde sogar die Empfehlung aussprechen und nach Möglichkeit auf die
Angabe von Datentypen im sizeof beim malloc-Argument komplett zu
verzichten und nach Möglichkeit immer alles über die Variable
abzuwickeln.
1
p=malloc(sizeof(*p));
bedeutet: Allokiere ein Objekt, so dass p auf dieses Objekt zeigt. p
weiß schon selber auf welchen Objekttyp es zeigen kann, das braucht mich
hier absolut nicht zu interessieren. Weder das /sizeof(struct foo)/ noch
der Cast des Returnwertes vom malloc tragen IMHO da irgendetwas zu
irgendeiner Klärung bei.
Jeder mag das halten wie er will. Ich werde auch weiterhin die
Empfehlung aussprechen, keinen Cast zu benutzen, der nicht absolut
notwendig ist. Und an dieser Stelle ist er nicht notwendig. Lasse ich
ihn weg und habe vergessen den Header reinzuholen, der malloc
deklariert, dann habe ich einen Error (Assignment makes pointer from
integer). Mache ich einen Cast, dann habe ich den Error je nach Compiler
auf entweder nichts oder eine Warnung reduziert. Aber der Code
compiliert in diesem Fall durch und kann fehlerhaftes Verhalten
hervorrufen wenn sizeof(int) != sizeof(void*).
Karl heinz Buchegger schrieb:
> Daher ist in C bei so etwas>> if( ptr )> free( ptr );>> bzw. in C++>> if( ptr )> delete ptr;>> die Abfrage des Pointer-Wertes eine sinnlose Aktion (in 99% aller Fälle)
Ein bisschen sinnvoller würde es, wenn der Pointer dann wirklich
ungültig gemacht würde:
Ulf Rolf schrieb:
> Ein bisschen sinnvoller würde es, wenn der Pointer dann wirklich> ungültig gemacht würde:> if (ptr) {> free (ptr);> ptr = 0;> }
1
free(ptr);
2
ptr=NULL;
Ist da aber exakt gleichbedeutend...
Auch möchte ich gerne nochmal Karl Heinz Buchegger unterstützen:
1
p=malloc(sizeof(*p));
Ist wohl die beste, am besten lesbare und portabelste Schreibweise. So
kann ich den Typ von p ändern und es funktioniert trotzdem noch.
Back to Topic: Ist der Fragesteller noch mit an Board und kann sich
melden, wenn ihm noch irgendwas unklar ist?