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.
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
Kommentare 0
Kommentare sind für diese Seite deaktiviert.