8

Alle Beispiele, die ich online über das Inkrementieren eines Zeigers finden konnte, der einen segfault verursacht, umfasste die Dereferenzierung des Zeigers - was, wenn ich nur inkrementieren möchte (zum Beispiel am Ende einer for-Schleife) und ich don Es ist mir egal, ob es in einem ungültigen Speicher landet, weil ich es nicht wieder benutzen werde. Zum Beispiel muss ich in diesem Programm nur jede Iteration um 4 schreiten, aber ich werde diese Zeiger nach der letzten Iteration nie wieder dereferenzieren.Kann ein Zeiger ohne Dereferenzierung noch segfault inkrementieren oder andere (un) definierte Gemeinheiten haben?

float* leftRowPointer, resultRowPointer; 
// assume they were correctly initialized 

for (unsigned int i = 0; i < 4; ++i, leftRowPointer += 4, resultRowPointer += 4) { 
    // do some stuff 
} 

Muss ich stattdessen so etwas tun?

for (unsigned int i = 0; i < 4; ++i) { 
    // same stuff 
    if (i != 3) { 
     leftRowPointer += 4; 
     resultRowPointer += 4; 
    } 
} 

Gibt es einen besseren Weg, um zu erreichen, was ich versuche zu tun?

Wenn ich es selbst versucht habe, scheint nichts Schlimmes zu passieren, aber das ist kaum eine Garantie, dass es immer funktioniert, und leider habe ich keinen Zugang zu Valgrind oder ähnlichem bei der Arbeit.

Wir verwenden den C++ 11-Standard, fwiw, und ich konnte dort nichts finden, was direkt darauf zutrifft, aber ich werde als erster zugeben, dass ich den Standard nicht gut kenne genug, um eine gute Vorstellung davon zu haben, wo man danach suchen sollte.

+1

Suchen Sie in additive Operatoren (wahrscheinlich [expr.plus] oder etwas wie §5.5). – chris

+0

Was sind die Typen 'leftRowPointer' und' resultRowPointer'? Im Allgemeinen ist das Inkrementieren von Zeigern sicher. Wenn es sich jedoch um einen benutzerdefinierten Typ mit einem überschriebenen Operator + = 'handelt, müssen Sie die Sicherheit der benutzerdefinierten Funktion überprüfen. – inetknght

+1

Dies könnte nützlich sein, um Ihre Frage zu beantworten: http://stackoverflow.com/questions/2728299/why-is-comparing-against-end-iterator-legal –

Antwort

8

Abschnitt 5.7, "Additive Operatoren", Absatz 5 spezifiziert dies - das Ergebnis der Addition selbst ist undefiniert; Das Programm ist nicht gültig, auch wenn Sie die Zeiger nie dereferenzieren.

Wenn sowohl der Zeigeroperanden und das Ergebnis Punkt auf Elemente des gleichen Array-Objekt oder ein hinter dem letzten Element des Arrays Objekt, Die Auswertung darf nicht einen Überlauf erzeugen; Andernfalls ist das Verhalten nicht definiert.

Es ist sehr unwahrscheinlich, segfault obwohl es erlaubt ist, aber es ist immer noch undefiniert mit allem, was dazu gehört.

4

Wenn nur das Zuweisen eines ungültigen Verweises zu einem Zeiger ein Problem war, wäre das Initialisieren eines zu NULL ebenfalls ein Problem. Die Antwort auf Ihre spezifische Frage lautet also "Nein".

+1

Ich glaube, es gibt tatsächlich einen Unterschied zwischen ungültigem Zeiger und Null. Und ich glaube, es gibt eine Mehrdeutigkeit im Standard, die es jemandem erlaubt, es so zu lesen, dass ein Zeiger einfach ungültig gemacht wird und ein undefiniertes Verhalten ausgelöst wird (etwas in der Zeile des nicht definierten Begriffs "verwenden"). Ich bin jedoch kein Sprachmittler und kann diesen Fall nicht bestreiten. – SergeyA

+0

Der Nullzeiger ist ein gültiger Zeigerwert. ("Ein gültiger Wert eines Objekt-Zeigertyps stellt entweder die Adresse eines Bytes im Speicher (1.7) oder einen Null-Zeiger dar" - 3.9.2 Zusammengesetzte Typen.) – molbdnilo