2 Stimmen

C++ Inkrementieren eines Zeigers in unbekanntes Speichergebiet

Ich habe eine Frage zum Verhalten von C/C++ bei der blinden Inkrementierung eines Zeigers.

Ich habe also einen Zeiger auf einen int als Parameter für eine Funktion

func(int* thePointer) {...

und ich habe eine Schleife innerhalb dieser Funktion

while(*thePointer) {
    ++thePointer;
}

Ich verstehe, dass, solange es int Die Schleife wird fortgesetzt, aber was ist, wenn der Speicher zu einem Teil eines anderen Speichertyps gehört? Angenommen, Sie inkrementieren in die ersten 4 Bytes eines double . Hat der int-Wert in diesem Fall noch einen Wert bzw. wird die Schleife fortgesetzt?

Haftungsausschluss: Ich weiß, dass dies höchstwahrscheinlich eine schlechte Praxis ist. Dies ist eine rein akademische Frage.

7voto

Pablo Santa Cruz Punkte 169147

Im Gedächtnis gibt es nicht so etwas wie eine int oder eine doppelt . Speicher ist einfach nur Speicher: Platzhalter für Bytes.

Wenn Sie also weiterhin einen Zeiger auf int verweisen Sie auf die nächsten vier Bytes im Speicher und das war's. Wenn Sie versuchen, diesen Teil des Speichers über den Zeiger auf Integer zu verwenden, werden Sie dessen Inhalt wahrscheinlich so behandeln, als wäre er ein int .

Schließlich werden Sie auf einen Bereich des Speichers zeigen, der Ihrem Prozess nicht zugewiesen ist, und Ihr Programm wird sich mit einer SEGMENTIERUNGSFEHLER .

4voto

Keith Punkte 6658

ISO 14882, Abschnitt 5.7:

$4 Für die Zwecke der Zeiger auf ein Nicht-Array-Objekt verhält sich genauso wie ein Zeiger auf das erste Element eines Arrays der Länge eins mit dem Typ des Objekts Typ.

$5 Wenn ein Ausdruck Integraltyp hat, wird zu einem Ausdruck addiert oder subtrahiert den Typ des Zeigeroperanden. Zeigt der Zeigeroperand auf ein Element eines Array-Objekts zeigt, und der Array groß genug ist, zeigt das Ergebnis auf ein Element, das gegenüber dem ursprünglichen Element, so dass die Differenz der Indizes des resultierenden und ursprünglichen Array-Elemente gleich dem Integralausdruck ist. In Mit anderen Worten: Wenn der Ausdruck P auf Objekts zeigt, sind die Ausdrücke (P)+N (gleichbedeutend N+(P)) und (P)N (wobei N den Wert n hat) auf, das i+n-te bzw. i- n-te Elemente des Array-Objekts, sofern sie existieren. Außerdem, wenn der Ausdruck P auf das letzte Element eines Arrays Ausdruck (P)+1 auf ein Element hinter dem letzten Element wenn der Ausdruck Q auf ein Element hinter das letzte Element zeigt der Ausdruck (Q)1 auf das letzte Element des Array-Objekts. Wenn sowohl der Zeigeroperand und das Ergebnis auf Elemente desselben Array Objekts zeigen, oder ein p des Array-Objekts zeigen, darf die Auswertung keinen Überlauf erzeugen; Andernfalls ist das Verhalten undefiniert.

2voto

Reed Copsey Punkte 536986

Was aber, wenn der Speicher zu einem Teil eines anderen Speichertyps gehört? Nehmen wir an, Sie inkrementieren in die ersten 4 Bytes eines Double. Hat der int dann noch einen Wert bzw. wird die Schleife in diesem Fall fortgesetzt?

Dem Compiler ist es egal, welche Art von Speicher vorhanden ist. Sie können in jeden beliebigen Speichertyp inkrementieren, und es wird gut sein.

Es wird nur dann ein Problem geben, wenn Sie versuchen Zugang diesen Speicherplatz. Wenn Sie versuchen, einen Wert an der Zeigerposition zu setzen, und es ist nicht der Ihrem Prozess zugewiesene Speicher, wird er abstürzen.

Solange der Speicher an dieser Stelle Ihnen gehört (d. h. Ihr Programm hat ihn zugewiesen), können Sie ihn einstellen. Das heißt, wenn der Speicherplatz nicht etwas war, das Sie als Integer-Wert behandelt haben, werden Sie höchstwahrscheinlich den Zustand eines anderen Objekts beschädigen, was schließlich zu schlechten Dingen führen wird.

1voto

Ich schließe mich allen an. Der Gedanke, dies zu tun, auch wenn es akademischen Zwecken dient, öffnet dem Teufel Tür und Tor. Der Zeiger wird jedes Mal um die Größe von int erhöht, egal was im Speicher ist. Wenn man darauf zugreift, wird man Müll erhalten.

1voto

Martin York Punkte 245363

Das Verschieben eines Zeigers ist gefährlich, wenn Sie auf den Speicher zugreifen (lesen oder schreiben).

Das Verschieben eines Zeigers über das Ende des aktuellen Objekts hinaus und das De-Referenzieren des Objekts ist ein undefiniertes Verhalten.

Einzelnes Objekt:

int  x;
int* xp = &x;

xp++; // Now pointing past the object.
int  y  = *xp; // Undefined behavior.

Array:

int  x[10];
int  xp = x;

while(*xp)
{   ++xp;  // Works fine the first 9 times.
}          // After that it is UB to access the memory pointed at by xp

Hinweis: bei Schleifenbildung

while(*xp)  // This continues while the memory pointed at
            // is not zero. As soon as a zero is found in memory
            // the loop exits.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X