Null Zeiger
Im Computer, a Null Zeiger oder NULL -Referenz ist ein Wert gespeichert, um anzuzeigen, dass die Zeiger oder Hinweis bezieht sich nicht auf eine gültige Objekt. Programme verwenden routinemäßig Null -Zeiger, um Bedingungen wie das Ende von a zu repräsentieren aufführen von unbekannter Länge oder dem Versäumnis, etwas Aktion auszuführen; Diese Verwendung von Nullzeiger kann verglichen werden Nullbare Typen und zum Nichts Wert in an Optionstyp.
Ein Nullzeiger sollte nicht mit einem verwechselt werden nicht initialisierter Zeiger: Ein Nullzeiger wird garantiert ungleich mit jedem Zeiger verglichen, der mit einem gültigen Objekt verweist. Abhängig von der Sprache und Implementierung hat ein nicht initialisierter Zeiger jedoch möglicherweise keine solche Garantie. Es könnte gleich mit anderen, gültigen Zeigern verglichen werden; oder es kann gleich Nullzeiger vergleichen. Es könnte beider Zeiten beides tun; oder der Vergleich könnte sein undefiniertes Verhalten.
C
Im C, zwei Nullzeiger jeglicher Art werden garantiert gleich vergleichen.[1] Das Präprozessor -Makro NULL
ist definiert als eine implementierungsdefinierte Nullzeigerkonstante,[2] welches in C99 kann portierbar ausgedrückt werden als ((void *) 0)
was bedeutet, dass der Ganzzahlwert 0
konvertiert in den Typ Leere*
(Zeiger auf Leere).[3] Der C -Standard sagt nicht, dass der Nullzeiger der gleiche ist wie der Zeiger Speicheradresse0, obwohl dies in der Praxis der Fall sein kann. Derference Ein Nullzeiger ist undefiniertes Verhalten in c,[4] und eine konforme Implementierung darf annehmen, dass jeder Zeiger, der Derferenziert ist, nicht null ist.
In der Praxis kann Dereferenzierung eines Nullzeigers dazu führen, dass ein Versuch gelesen oder geschrieben wird Erinnerung das ist nicht zugeordnet und löst a aus Segmentierungsfehler oder Speicherzugriffsverletzung. Dies kann sich als Programmabsturz manifestieren oder in eine Software umgewandelt werden Ausnahme Das kann durch den Programmcode erfasst werden. Es gibt jedoch bestimmte Umstände, unter denen dies nicht der Fall ist. Zum Beispiel in x86 Realer Modus, die Adresse 0000: 0000
ist lesbar und auch in der Regel beschreibbar, und Derferen eines Zeigers auf diese Adresse ist eine vollkommen gültige, aber normalerweise unerwünschte Aktion, die zu undefiniertem, aber nicht-kratzendem Verhalten in der Anwendung führen kann. Es gibt Fälle, in denen der Zeiger zur Behandlung von Null ist absichtlich und gut definiert; zum Beispiel, BIOS Code in C für 16-Bit-Real-Mode-X86-Geräte können die schreiben Idt An der physischen Adresse 0 der Maschine durch Dereferenzierung eines Nullzeigers zum Schreiben. Es ist auch dem Compiler möglich, die Nullzeiger -Dereferenz zu optimieren, ein Segmentierungsfehler zu vermeiden, aber andere verursacht unerwünschtes Verhalten.
C ++
In C ++, während die NULL
Makro wurde von C geerbt, wobei traditionell das Ganzzahl -Literal für Null eine Nullzeigerkonstante darstellt.[5] Jedoch, C ++ 11 hat die explizite Nullzeigerkonstante eingeführt nullptr
stattdessen verwendet werden.
Andere Sprachen
In einigen Programmiersprachumgebungen (z. Null
in Lispeln) kann tatsächlich ein Zeiger auf einen Block interner Daten sein, der für die Implementierung nützlich ist (aber nicht explizit von Benutzerprogrammen erreichbar ist), sodass dasselbe Register als nützliche Konstante und schnelle Möglichkeit zum Zugriff auf Implementierungsinteralen verwendet werden kann. Dies ist als die bekannt Null
Vektor.
In Sprachen mit a Tagged Architektur, ein möglicherweise Nullzeiger kann durch a ersetzt werden Tagged Union Dies erzwingt die explizite Umstellung des Ausnahmefalls; In der Tat kann ein möglicherweise Nullzeiger als als gesehen werden Tagged Zeiger mit einem berechneten Tag.
Programmiersprachen verwenden verschiedene Literale für die Null Zeiger. In Python zum Beispiel wird ein Nullwert genannt Keiner
. Im Pascal und Schnell, ein Nullzeiger heißt Null
. Im Eiffel, es wird a genannt Leere
Hinweis.
Null Dereferencing
Weil ein Nullzeiger nicht auf ein aussagekräftiges Objekt verweist, einen Versuch zu Dereferenz (d. H. Zugreifen auf die an diesem Speicherort gespeicherten Daten) Ein Nullzeiger führt normalerweise (aber nicht immer) einen Laufzeitfehler oder einen sofortigen Programmabsturz.
- Im C, Derferenzieren ein Nullzeiger ist undefiniertes Verhalten.[4] Viele Implementierungen führen dazu, dass ein solcher Code dazu führt, dass das Programm mit einem gestoppt wird Zugriffsverletzung, weil die Repräsentation der Nullzeiger als eine Adresse ausgewählt wird, die vom System niemals zum Speichern von Objekten zugewiesen wird. Dieses Verhalten ist jedoch nicht universell. Es ist auch nicht garantiert, da Compiler Programme optimieren dürfen, unter der Annahme, dass sie frei von undefiniertem Verhalten sind.
- Im Delphi und viele andere Pascal -Implementierungen, die Konstante
Null
repräsentiert einen Nullzeiger auf die erste Adresse im Speicher, mit der auch verwaltete Variablen initialisiert werden. Dereferenzieren Sie eine externe OS -Ausnahme, die auf eine Ausnahmeinstanz von Pascal Eaccessviolation zugeordnet wird. - Im Java, Zugang zu einer Nullreferenz löst a
NullPointerexception
(NPE), das durch Fehlerhandelcode erfasst werden kann, aber die bevorzugte Praxis besteht darin, sicherzustellen, dass solche Ausnahmen niemals auftreten. - Im Lispeln, nil ist a erstklassiges Objekt. So
(First Nil)
ist nil und(Rest nil)
ist nil. Dereferencing Nil verursacht also keinen Fehler, aber schlecht geschriebener Code kann in eine unendliche Schleife geraten. - Im .NETZDer Zugriff auf Null -Referenz löst eine NullRreferencexception aus. Obwohl das Fangen im Allgemeinen als schlechte Praxis angesehen wird, kann dieser Ausnahmeart vom Programm gefangen und behandelt werden.
- Im Ziel c, Nachrichten können an a gesendet werden
Null
Objekt (das ein Nullzeiger ist), ohne dass das Programm unterbrochen wird; Die Nachricht wird einfach ignoriert und der Rückgabewert (falls vorhanden) istNull
oder0
, abhängig vom Typ.[6] - Vor der Einführung von SMAPEin Nullzeiger -Dereference -Fehler könnte durch Mapping ausgenutzt werden Pagezero in den Angreifer Adressraum und damit den Nullzeiger auf diese Region hinweist. Dies könnte dazu führen Codeausführung in manchen Fällen.[7]
Minderung
Es gibt Techniken zur Erleichterung des Debugging -Nullzeigers.[8][9] Bond et al.[8] Schlagen Sie vor, die JVM zu ändern, um die Nullausbreitung im Auge zu behalten. Die Idee des Casper -Systems[9] ist die Verwendung von Quellcode -Transformation, um diese Ausbreitung zu verfolgen, ohne das JVM zu ändern. In einigen Fällen ist es möglich, automatisch ein Patch zu generieren, um Nullzeigerausnahmen zu beheben.[10]
Rein Funktionssprachenund Benutzercode in vielen ausgeführt interpretiert oder virtuelle Maschinensprachen erleiden nicht das Problem der Nullzeiger-Derercencing, da Hinweise kein direkter Zugriff erteilt und im Fall reiner funktionaler Sprachen alle Code und Daten unveränderlich sind.
Wenn eine Sprache Zeiger bereitstellt oder verwendet, die sonst ungültig werden könnten, kann es möglich sein, Laufzeit-Null-Dereferenzen zu mildern oder zu vermeiden Statische Analyse oder andere Techniken mit einer aufkeimenden Bewegung in Richtung syntaktischer Unterstützung von Sprachmerkmalen, wie sie in modernen Versionen des Eiffel -Programmiersprache,[11] D,[12] und Rost.[13]
Eine ähnliche Analyse kann in einigen Sprachen mit externen Tools durchgeführt werden.
Geschichte
Im Jahr 2009, Sir Tony Hoare angegeben[14] dass er die Nullreferenz 1965 als Teil der erfunden hat Algol w Sprache. In dieser 2009er Referenz beschreibt Hoare seine Erfindung als "Milliarden-Dollar-Fehler":
Ich nenne es meinen Milliarden-Dollar-Fehler. Es war die Erfindung der Null -Referenz im Jahr 1965. Zu diesem Zeitpunkt habe ich das erste umfassende Typsystem für Referenzen in einer objektorientierten Sprache (Algol W) entworfen. Mein Ziel war es, sicherzustellen, dass die gesamte Verwendung von Referenzen absolut sicher sein sollte, wobei die Überprüfung vom Compiler automatisch durchgeführt wird. Aber ich konnte der Versuchung nicht widerstehen, eine Nullreferenz einzulegen, einfach weil es so einfach zu implementieren war. Dies hat zu unzähligen Fehlern, Schwachstellen und Systemunfällen geführt, die in den letzten vierzig Jahren wahrscheinlich eine Milliarde Dollar an Schmerzen und Schäden verursacht haben.
Siehe auch
Verweise
Zitate
- ^ ISO/IEC 9899, Klausel 6.3.2.3, Absatz 4.
- ^ ISO/IEC 9899, Klausel 7.17, Absatz 3: Null ... was zu einer implementierungsdefinierten Nullzeigerkonstante erweitert ...
- ^ ISO/IEC 9899, Klausel 6.3.2.3, Absatz 3.
- ^ a b ISO/IEC 9899, Klausel 6.5.3.2, Absatz 4, insb. Fußnote 87.
- ^ Stroustrup, Bjarne (März 2001). "Kapitel 5:
DasConst
Qualifikation (§5.4) verhindert eine versehentliche Neudefinition vonNULL
und sorgt dafürNULL
kann verwendet werden, wo eine Konstante benötigt wird. ". Die C ++ - Programmiersprache (14. Druck von 3. Aufl.). USA und Kanada: Addison -Wesley. p.88. ISBN 0-201-88954-4. - ^ Die Programmiersprache für Objektiv-C 2.0, Abschnitt "Nachrichten an Null senden".
- ^ OS X Ausstellbarer Kernel -Nullzeiger Dereferenz in appraphicsdeviceControl
- ^ a b Bond, Michael D.; Nethercote, Nicholas; Kent, Stephen W.; Guyer, Samuel Z.; McKinley, Kathryn S. (2007). "Bad Äpfel verfolgen". Verfahren der 22. jährlichen ACM -Sigplan -Konferenz über objektorientierte Programmiersysteme und Anwendungen - OOPSLA '07. p. 405. doi:10.1145/1297027.1297057. ISBN 9781595937865. S2CID 2832749.
- ^ a b Cornu, Benoit; Barr, Earl T.; Seinturier, Lionel; Monperrus, Martin (2016). "Casper: Automatische Verfolgung von Null Dereferenzen bis zur Inception mit Kausalitätsspuren". Zeitschrift für Systeme und Software. 122: 52–62. Arxiv:1502.02004. doi:10.1016/j.js.2016.08.062. ISSN 0164-1212.
- ^ Durieux, Thomas; Cornu, Benoit; Seinturier, Lionel; Monperrus, Martin (2017). "Dynamische Patch -Erzeugung für Nullzeigerausnahmen mithilfe von Metaprogrammierung" (PDF). 2017 IEEE 24. Internationale Konferenz für Softwareanalyse, Evolution und Reengineering (saner). IEEE: 349–358. Arxiv:1812.00409. doi:10.1109/saner.2017.7884635. ISBN 978-1-5090-5501-2. S2CID 2736203.
- ^ "Leersicherheit: Hintergrund, Definition und Werkzeuge". Abgerufen 2021-11-24.
- ^ Bartosz Milewski. "Safed - D Programmiersprache". Abgerufen 17. Juli 2014.
- ^ "Fearless Security: Speichersicherheit". Archiviert vom Original am 8. November 2020. Abgerufen 4. November 2020.
- ^ Tony Hoare (2009-08-25). "NULL REFERENZEN: Der Milliarden -Dollar -Fehler". Infoq.com.
Quellen
- Joint Technical Committee ISO/IEC JTC 1, Unterausschuss SC 22, Arbeitsgruppe WG 14 (2007-09-08). Internationales Standard -ISO/IEC 9899 (PDF) (Ausschussentwurf).
{{}}
: Cs1 montiert: Mehrfachnamen: Autorenliste (Link)