Forum: PC-Programmierung C - realloc() direkt verwenden


von max .. (vbc2011)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

ja ist zulässig und macht auch keine Probleme

von Εrnst B. (ernst)


Lesenswert?

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.

von DirkB (Gast)


Lesenswert?

Ε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.

von 123gast (Gast)


Lesenswert?

@DirkB
Guck mal genau hin, wo ist der Unterschied?

     *ptr=NULL;
char *ptr=NULL

von 123gast (Gast)


Lesenswert?

Sorry, Semikolon vergessen.

von DirkB (Gast)


Lesenswert?

123gast schrieb:
> @DirkB
> Guck mal genau hin, wo ist der Unterschied?

Danke für die Brille.

von Εrnst B. (ernst)


Lesenswert?

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.

von 123gast (Gast)


Lesenswert?

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
}

von 123gast (Gast)


Lesenswert?

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
//...

von 123gast (Gast)


Lesenswert?

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...

von Klaus W. (mfgkw)


Lesenswert?

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 :-)

von Rolf Magnus (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.