Hallo, ich möchte mir einen Schritt beim dynamischen Speicher allokieren sparen. Indem ich calloc() weglasse und direkt realloc() verwende. Mein Programm funktioniert auch soweit - ich möchte nur wissen ob es evtl. Randeffekte haben kann - da die korrekte Verwendung von realloc() ja zum erweitern eines schon vorhandnen Speichers ist!! .... *ptr = NULL; ptr = (char *) realloc( ptr, Size ); ..... Es funktioniert deswegen - weil der Pointer, an der Stelle wo der Speicher erweitert werden soll - auf NULL zeigt!??! Hat da jemand Erfahrung?
max .. schrieb: > *ptr = NULL [...] > weil der Pointer, an der Stelle wo der > Speicher erweitert werden soll - auf NULL zeigt!??! Das macht deine Zeile oben aber nicht. Die schreibt, egal wohin der Pointer gerade zeigt, eine 0. Der Pointer zeigt also anschliessend nicht auf die Speicherstelle NULL, sondern auf (irgend-)eine Speicherstelle, die die Zahl 0 enthält.
Εrnst B✶ schrieb: > Das macht deine Zeile oben aber nicht. Die schreibt, egal wohin der > Pointer gerade zeigt, eine 0. > Der Pointer zeigt also anschliessend nicht auf die Speicherstelle NULL, > sondern auf (irgend-)eine Speicherstelle, die die Zahl 0 enthält. Seit wann denn? Dann würden ja Millonen LoC nicht mehr funktionieren. Es geht auch { int *ptr = NULL; int i; int *pi = &i; Dann zeigt ptr auf NULL und pi zeigt auf i.
@DirkB Guck mal genau hin, wo ist der Unterschied? *ptr=NULL; char *ptr=NULL
DirkB schrieb: > Seit wann denn? Schon immer? > Dann würden ja Millonen LoC nicht mehr funktionieren. Nö... bei neueren Betrübssystemen gibts da nen Segfault/GPF, der Fehler wird schnell gefunden und ausgebessert. 123gast schrieb: > *ptr=NULL; > char *ptr=NULL; Aus dem Grund scheibe ich bei Pointer-Deklarationen gern das '*'-chen an den Typ. Also
1 | char x; |
2 | char* ptr=NULL; // ptr zeigt auf NULL |
3 | ptr=&x; // ptr zeigt auf x; |
4 | *ptr='a'; // x enthält jetzt 'a' |
5 | ptr=NULL; // ptr zeigt wieder auf NULL |
6 | *ptr='b'; // Segfault |
So ist auf einen Blick deutlich, ob ich einen Pointer anlege (int* z) oder ob ich einen Pointer dereferenziere (*z). Nur
1 | int* a,b; |
macht halt nicht das, was man vielleicht im ersten Moment erwarten würde.
DirkB schrieb: > 123gast schrieb: >> @DirkB >> Guck mal genau hin, wo ist der Unterschied? > > Danke für die Brille. Gerne. :-) Noch eine (wie ich finde nicht ganz unwichtige) Anmerkung zu realloc(): Das hier
1 | ptr = NULL; //KEIN STERN! |
2 | ptr = (char *) realloc( ptr, Size ); |
ist vollkommen in Ordnung, birgt aber die Gefahr von Speicherlecks:
1 | ptr=NULL; |
2 | ptr=realloc(ptr,sz); |
3 | if(!ptr) |
4 | {
|
5 | ...
|
6 | }
|
7 | //bisher alles OK, aber jetzt
|
8 | if(sz_needed>sz) //wir brauchen mehr Platz! |
9 | {
|
10 | ptr=realloc(ptr,sz_needed); //GEFAHR |
11 | if(!ptr) |
12 | {
|
13 | ...
|
14 | }
|
15 | }
|
16 | //...
|
Wenn der zweite Aufruf von realloc aus Speichermangel fehlschlägt bekommt ptr den Wert NULL zugwiesen, der Pointer auf den ersten angeforderten Bereich verschwindet. Es ist also nicht mehr möglich diesen Speicher freizugeben -->Speicherleck. OK, wenn man das Programm bei einem solchen Fehler mit exit(42) beendet ist das egal, im gegenteiligen Fall könnte das aber zum Problem werden. Lösung:
1 | char* ptr,ptr_tmp; |
2 | //...
|
3 | //mehr Speicher bitte
|
4 | ptr_tmp=realloc(ptr,sz); |
5 | if(!ptr_tmp) |
6 | {
|
7 | //Problem
|
8 | }
|
9 | else //Kann man weglassen wenn bei Problemen das Programm beendet wird |
10 | {
|
11 | ptr=ptr_tmp; |
12 | //...
|
13 | }
|
Oh Oh, ganz schlecht formuliert. :-(
>else //Kann man weglassen wenn bei Problemen das Programm beendet wird
Soll heißen: Die if-Abfrage bekommt keinen else-Zweig sondern es geht
direkt darunter weiter. Die Zuweisung ist natürlich trotzdem nötig!
1 | if(!ptr_tmp) |
2 | {
|
3 | //...
|
4 | exit(42); |
5 | }
|
6 | ptr=ptr_tmp; |
7 | //...
|
ARGH! Es wurde doch oben extra angesprochen. Falsch: char* ptr,ptr_tmp; Richtig: char* ptr, *ptr_tmp; Ich glaub ich lasse lieber die Finger von jeglichem Code heute...
123gast schrieb: > Falsch: > char* ptr,ptr_tmp; > Richtig: > char* ptr, *ptr_tmp; genau deshalb schreibe ich das Sternchen immer vor den Namen, nicht hinter den Typ :-)
Klaus Wachtler schrieb: > 123gast schrieb: >> Falsch: >> char* ptr,ptr_tmp; >> Richtig: >> char* ptr, *ptr_tmp; > > genau deshalb schreibe ich das Sternchen immer vor den Namen, nicht > hinter den Typ :-) Ich schreibe (nicht nur) aus diesem Grund einfach gar keine solchen kombinierten Definitionen. Deine Schreibweise ist zwar die von den C-Erfindern vorgesehene, aber meiner Meinung nach wenig intuitive Variante. Das Sternchen ist Teil des Typs und nicht Teil des Namens.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.