Ich habe C ++ gelernt und es fällt mir schwer, null zu verstehen. Insbesondere in den von mir gelesenen Tutorials wird erwähnt, dass ein "Null-Check" durchgeführt wird. Ich bin mir jedoch nicht sicher, was dies bedeutet oder warum dies erforderlich ist.
- Was genau ist null?
- Was bedeutet es, auf Null zu prüfen?
- Muss ich immer auf null prüfen?
Irgendwelche Codebeispiele wären sehr dankbar.
Antworten:
In C und C ++ sind Zeiger von Natur aus unsicher. Wenn Sie also einen Zeiger dereferenzieren, liegt es in Ihrer eigenen Verantwortung, sicherzustellen, dass er irgendwo gültig ist. Dies ist ein Teil dessen, worum es bei der "manuellen Speicherverwaltung" geht (im Gegensatz zu den in Sprachen wie Java, PHP oder der .NET-Laufzeit implementierten automatischen Speicherverwaltungsschemata, mit denen Sie keine ungültigen Referenzen ohne erheblichen Aufwand erstellen können).
Eine häufige Lösung, die viele Fehler abfängt, besteht darin, alle Zeiger zu setzen, die nicht auf irgendetwas verweisen
NULL
(oder in korrektem C ++0
), und dies zu überprüfen, bevor auf den Zeiger zugegriffen wird. Insbesondere ist es üblich, alle Zeiger auf NULL zu initialisieren (es sei denn, Sie haben bereits etwas, auf das Sie beim Deklarieren verweisen sollen), und sie auf NULL zu setzen, wenn Siedelete
oderfree()
sie dies tun (es sei denn, sie verlieren unmittelbar danach ihren Gültigkeitsbereich). Beispiel (in C, aber auch in C ++):Eine bessere Version:
Ohne die Null-Prüfung führt die Übergabe eines NULL-Zeigers an diese Funktion zu einem Segfault, und Sie können nichts tun - das Betriebssystem beendet einfach Ihren Prozess und führt möglicherweise einen Core-Dump durch oder öffnet ein Dialogfeld mit Absturzberichten. Mit der Null-Prüfung können Sie die Fehler ordnungsgemäß behandeln und ordnungsgemäß beheben. Beheben Sie das Problem selbst, brechen Sie den aktuellen Vorgang ab, schreiben Sie einen Protokolleintrag, und benachrichtigen Sie den Benutzer, was auch immer angemessen ist.
quelle
Die anderen Antworten deckten so ziemlich Ihre genaue Frage ab. Es wird eine Nullprüfung durchgeführt, um sicherzustellen, dass der Zeiger, den Sie erhalten haben, tatsächlich auf eine gültige Instanz eines Typs (Objekte, Grundelemente usw.) verweist.
Ich werde hier jedoch meine eigenen Ratschläge hinzufügen. Vermeiden Sie Nullprüfungen. :) Null überprüft (und andere Formen der defensiven Programmierung) den Code auf Unordnung und macht ihn tatsächlich fehleranfälliger als andere Fehlerbehandlungstechniken.
Meine bevorzugte Technik bei Objektzeigern ist die Verwendung des Null-Objektmusters . Das bedeutet, dass ein (Zeiger - oder noch besser, ein Verweis auf ein) leeres Array oder eine leere Liste anstelle von null oder eine leere Zeichenfolge ("") anstelle von null oder sogar die Zeichenfolge "0" (oder etwas, das "nichts" entspricht) zurückgegeben wird msgstr "in dem Kontext), in dem erwartet wird, dass es in eine ganze Zahl zerlegt wird.
Als Bonus haben Sie vielleicht etwas Unbekanntes über den Nullzeiger erfahren, der 1965 von CAR Hoare (erstmals offiziell) für die Sprache Algol W implementiert wurde.
quelle
Der Nullzeigerwert repräsentiert ein wohldefiniertes "Nirgendwo". Es handelt sich um einen ungültigen Zeigerwert, der garantiert mit keinem anderen Zeigerwert verglichen werden kann. Der Versuch, einen Nullzeiger zu dereferenzieren, führt zu undefiniertem Verhalten und führt normalerweise zu einem Laufzeitfehler. Stellen Sie daher sicher, dass ein Zeiger nicht NULL ist, bevor Sie ihn dereferenzieren. Eine Reihe von C- und C ++ - Bibliotheksfunktionen geben einen Nullzeiger zurück, um einen Fehlerzustand anzuzeigen. Beispielsweise gibt die Bibliotheksfunktion
malloc
einen Nullzeigerwert zurück, wenn sie die Anzahl der angeforderten Bytes nicht zuordnen kann, und der Versuch, über diesen Zeiger auf den Speicher zuzugreifen, führt (normalerweise) zu einem Laufzeitfehler:Wir müssen also sicherstellen, dass der
malloc
Aufruf erfolgreich war, indem wir den Wert vonp
gegen NULL prüfen :Bleib eine Minute bei deinen Socken, das wird ein bisschen holprig.
Es gibt einen Nullzeiger - Wert und eine Null - Zeiger - Konstante , und die beiden sind nicht notwendigerweise gleich. Der Null - Zeiger - Wert ist , was die zugrunde liegende Architektur Nutzungen schätzen „nirgendwo“ darzustellen. Dieser Wert kann 0x00000000 oder 0xFFFFFFFF oder 0xDEADBEEF oder etwas völlig anderes sein. Gehen Sie nicht davon , dass der Null - Zeiger - Wert ist immer 0.
Der Nullzeiger Konstante OTOH ist immer ein ganzzahliger Ausdruck mit dem Wert 0. Für Ihren Quellcode steht 0 (oder ein ganzzahliger Ausdruck, der mit 0 bewertet wird) für einen Nullzeiger. Sowohl C als auch C ++ definieren das NULL-Makro als Nullzeiger-Konstante. Wenn Ihr Code kompiliert wird, wird die Nullzeiger- Konstante durch den entsprechenden Nullzeiger- Wert im generierten Maschinencode ersetzt.
Beachten Sie außerdem, dass NULL nur einer von vielen möglichen ungültigen Zeigerwerten ist. Wenn Sie eine Auto-Pointer-Variable deklarieren, ohne sie explizit zu initialisieren, wie z
Der ursprünglich in der Variablen gespeicherte Wert ist unbestimmt und entspricht möglicherweise nicht einer gültigen oder zugänglichen Speicheradresse. Leider gibt es keine (portable) Möglichkeit, festzustellen, ob ein Zeigerwert ungleich NULL gültig ist oder nicht, bevor Sie versuchen, ihn zu verwenden. Wenn Sie es also mit Zeigern zu tun haben, ist es normalerweise eine gute Idee, sie explizit auf NULL zu initialisieren, wenn Sie sie deklarieren, und sie auf NULL zu setzen, wenn sie nicht aktiv auf irgendetwas zeigen.
Beachten Sie, dass dies in C eher ein Problem ist als in C ++. idiomatisches C ++ sollte nicht allzu oft Zeiger verwenden.
quelle
Es gibt ein paar Methoden, die alle im Wesentlichen dasselbe tun.
null check (prüfe, ob der Zeiger null ist), Version A
Null-Check, Version B
Null-Check, Version C
Von den dreien bevorzuge ich die erste Prüfung, da sie zukünftigen Entwicklern explizit mitteilt, worauf Sie zu prüfen versuchten, UND es verdeutlicht, dass Sie erwartet haben, dass foo ein Zeiger ist.
quelle
Das tust du nicht. Der einzige Grund für die Verwendung eines Zeigers in C ++ besteht darin, dass Sie explizit das Vorhandensein von Nullzeigern wünschen. Andernfalls können Sie eine Referenz verwenden, die semantisch einfacher zu verwenden ist und garantiert, dass sie nicht null ist.
quelle
export
) und alle C ++ 03-Bibliotheksfunktionen sowie TR1 und einen guten Teil von C ++ 11.Wenn Sie den NULL-Wert nicht überprüfen, insbesondere wenn dies ein Zeiger auf eine Struktur ist, ist möglicherweise eine Sicherheitslücke aufgetreten - NULL-Zeiger-Dereferenzierung. Eine NULL-Zeiger-Dereferenzierung kann zu einigen anderen schwerwiegenden Sicherheitslücken wie Pufferüberlauf, Race Condition ... führen, durch die Angreifer die Kontrolle über Ihren Computer erlangen können.
Viele Softwareanbieter wie Microsoft, Oracle, Adobe, Apple ... veröffentlichen Software-Patches, um diese Sicherheitslücken zu schließen. Ich denke, Sie sollten NULL-Wert jedes Zeigers überprüfen :)
quelle