2013-07-29 6 views
10

Ich war Richard Reeses neues (Mai 2013) O'Reilly Buch „Verstehen und Verwenden von C Pointers“ zu lesen, und ich habe eine Frage zu einigem Code darin, auf Seite 87.Originalzeiger nach Realloc verwenden?

if (++length > maximumLength) { 
    char *newBuffer = realloc (buffer, maximumLength += sizeIncrement); 

    if (newBuffer == NULL) { 
     free (buffer); 
     return NULL; 
    } 

    currentPosition = newBuffer + (currentPosition - buffer); 
    buffer = newBuffer; 
} 

ich den Namen Hoffnung die Variablen sind selbsterklärend; Wenn ein Kontext benötigt wird, werde ich bearbeiten, um den gesamten Code und nicht nur diesen Auszug bereitzustellen.

Meine Frage ist über die Linie currentPosition = newBuffer + (currentPosition - buffer);. Mein Verständnis von ist, dass, wenn die neue Zuweisung erfolgreich ist, der ursprünglich zugewiesene Speicher freigegeben wird. Wenn das richtig ist, dann verwendet die fragliche Zeile hängende Zeiger, innit? Sowohl buffer als auch currentPosition auf dem RHS dieses Ausdrucks sind Zeiger auf Speicher, der freigegeben wurde.

Mein Instinkt wäre, dies neu zu schreiben, um zu vermeiden, die baumelnden Zeiger zu verwenden, indem man length verwendet, das schließlich schon herum ist. Ich möchte mit diesen beiden letzten Zeilen ersetzen:

buffer = newBuffer; 
currentPosition = buffer + length; 

jedoch vermutlich der Code geschrieben funktioniert, weil die beiden Zeiger noch Adressen halten (wenn auch von Müll) und die zwischen diesen beiden Adressen-Offset kann noch berechnet werden eine Art der Neuzuweisung currentPosition. Bin ich also nur pedantisch darin, mich darüber unwohl zu fühlen?

Verallgemeinerung der Frage: Sobald ein Zeiger schwankt, ist es sicher, die im Zeiger enthaltene Adresse für irgendeinen Zweck zu verwenden, wie zum Beispiel das Berechnen von Offsets? Vielen Dank.

+0

Zum Zeitpunkt der Neuzuweisung ist 'length' um eins größer als die Größe des Puffers (' maximumLength' vor der Anpassung). Sie sollten 'currentPosition = buffer + length-1' verwenden, wenn ich die Bedeutungen richtig interpretiere. – Casey

+0

Ich habe das überprüft, bevor ich die Frage gestellt habe. Der Buchcode initialisiert sowohl "length" als auch "currentPosition" auf null. 'length' wird in der ersten Bedingung inkrementiert, also ist es immer eine nach dem Index des zuletzt hinzugefügten Elements. 'currentPosition' ist die Stelle, an der das neue Element hinzugefügt werden soll, und wird nach dem Hinzufügen inkrementiert. Dies ist nicht so, wie ich den Code geschrieben hätte, aber mit dem gegebenen Code ist "Puffer + Länge" korrekt. – verbose

+0

Also 'currentPosition' ist eine vorkompilierte' Puffer + Länge'? Ich stehe korrigiert (und etwas verwirrt von der Redundanz). – Casey

Antwort

9

Wenn ein Zeiger schwankt, kann die im Zeiger enthaltene Adresse für jeden Zweck verwendet werden, z. B. für die Berechnung von Offsets?

Nein, es ist nicht sicher. Nach free ist der Zeigerwert eine ungültige Adresse und eine ungültige Adresse kann nicht für Zeigerarithmetik verwendet werden, ohne undefiniertes Verhalten aufzurufen.

+0

Quelle? Das hätte ich nicht erwartet. –

+2

@CoryNelson C11, 6.5.6p8 Zeigerarithmetik. Wenn das Ergebnis nicht im Array-Objekt oder hinter dem letzten Element liegt => undefiniertes Verhalten. – ouah

+1

@Ouah, ich denke, dass bezieht sich auf, wenn Sie versuchen, das Ergebnis dereferenzieren. – ROTOGG

0

Es ist sicher, den ungeeigneten Zeiger zu verwenden (z. B. für "Zeigerarithmetik"), solange Sie nicht versuchen, den Zeiger zu dereferenzieren (d. H. Den Operator * anwenden).

+3

Das ist falsch, weil der C-Standard nicht garantiert, dass die Arithmetik von früheren Zeigern auf nicht mehr existierende Objekte funktioniert. Sie könnten argumentieren, dass Zeiger als Speicheradressen implementiert sind, und arithmetische Operationen auf Adressen funktionieren offensichtlich, Zeiger sind jedoch nicht unbedingt auf diese Weise implementiert. Zusätzlich kann der Optimierer Ableitungen basierend auf den Regeln von C vornehmen, was zu einem überraschenden Verhalten führen kann. –