C++
VeröffentlichtRevision 1

Zeigerfallen: Grenzen, C-Strings und dangling

Ein Speicherfehler entsteht beispielsweise, wenn Code außerhalb gültiger Objekte liest, schreibt oder auf bereits freigegebenen Speicher zugreift. In C++ führen viele dieser Fehler zu undefiniertem Verhalten. „Es hat beim Test funktioniert“ ist deshalb kein Gültigkeitsnachweis.

Zeigerfallen: Grenzen, C-Strings und dangling#

Referenzen, Zeiger und Speicher · Lektion 35 von 60

Voraussetzungen: Zeiger, Arrays. Lernziel: Du erkennst Speicherfehler vor dem Zugriff.

Ein Speicherfehler entsteht beispielsweise, wenn Code außerhalb gültiger Objekte liest, schreibt oder auf bereits freigegebenen Speicher zugreift. In C++ führen viele dieser Fehler zu undefiniertem Verhalten. „Es hat beim Test funktioniert“ ist deshalb kein Gültigkeitsnachweis.

Zeigerarithmetik ist begrenzt#

Zeigerarithmetik verschiebt einen Zeiger in Einheiten seines Zieltyps. Bei int* bedeutet p + 1 das nächste int-Element, nicht das nächste Byte. Solche Rechnungen sind nur innerhalb eines passenden Arrays einschließlich der Position direkt dahinter zulässig.

C++
1#include <iostream>2 3int main() {4    int zahlen[3]{10, 20, 30};5    int* anfang = zahlen;6    int* ende = zahlen + 3;7    for (int* position = anfang; position != ende; ++position) {8        std::cout << *position << '\n';9    }10}

ende darf verglichen, aber nicht dereferenziert werden. Auch das bloße Berechnen weit außerhalb des erlaubten Arraybereichs ist nicht allgemein zulässig. Ziehe keine Zeiger auf voneinander unabhängige Objekte voneinander ab.

Häufige Fehlerbegriffe#

Begriff

Bedeutung

Vorbeugung

Null dereference

Zugriff über einen Nullzeiger

Gültiges Ziel verlangen oder null behandeln

Out-of-bounds

Zugriff außerhalb des gültigen Bereichs

Länge mitführen, Grenzen prüfen

Dangling pointer

Zeiger ohne lebendes ursprüngliches Ziel

Lebensdauer beachten

Use-after-free

Zugriff nach Speicherfreigabe

Besitz klar regeln, verwaltende Typen nutzen

Double free

Derselbe Speicher wird zweimal freigegeben

Genau einen passenden Besitzer verwenden

Das Setzen eines Zeigers auf nullptr nach einer Freigabe repariert keine anderen Kopien desselben Adresswerts. Auch eine Vector-Reallokation kann gespeicherte Elementzeiger ungültig machen.

C-Strings sind nicht bloß beliebige Adressen#

Ein C-String ist eine Zeichenfolge mit abschließendem Nullzeichen \0. std::cout behandelt const char* standardmäßig als solchen Text und nicht als numerische Adresse. Fehlt die Endmarkierung in lesbarem Speicher, kann die Ausgabe über den erlaubten Bereich hinaus lesen.

Für die Adressdarstellung eines gültigen Zeichenzeigers kannst du ihn zu const void* umwandeln. void* bezeichnet einen Objektzeiger ohne konkreten Zieltyp für den unmittelbaren Zugriff. Für alltägliche Texte ist std::string meist einfacher.

Übung#

Ein Zeiger zeigt auf vector.at(0). Danach wächst der Vector. Reicht eine Nullprüfung vor dem nächsten Zugriff?

Lösung

Nein. Wachstum kann den Speicher verlagern. Ermittle den Zugriff nach der Änderung neu oder gestalte den Ablauf so, dass keine ungültigen Verweise aufbewahrt werden.

Weiterlernen#

Zurück: Zeiger, nullptr und Dereferenzieren · Kursübersicht · Weiter: Dynamischer Speicher, new/delete und RAII

Mitwirkende 1

Menschen, deren Änderungen in dieser Seite veröffentlicht wurden.

Kommentare 0

Kommentare sind für diese Seite deaktiviert.