In Ihrem Beispiel myApple
hat der spezielle Wert null
(normalerweise alle Null-Bits) und verweist daher auf nichts. Das Objekt, auf das es ursprünglich verwiesen hat, ist jetzt auf dem Heap verloren. Es gibt keine Möglichkeit, seinen Standort abzurufen. Dies ist bei Systemen ohne Garbage Collection als Speicherverlust bekannt.
Wenn Sie ursprünglich 1000 Referenzen auf Null gesetzt haben, haben Sie nur Platz für 1000 Referenzen, normalerweise 1000 * 4 Bytes (auf einem 32-Bit-System doppelt so viel wie auf 64). Wenn diese 1000 Referenzen ursprünglich auf reale Objekte verweisen, haben Sie jedem Objekt die 1000-fache Größe zuzüglich des Platzes für die 1000 Referenzen zugewiesen.
In einigen Sprachen (wie C und C ++) zeigen Zeiger immer auf etwas, auch wenn sie "nicht initialisiert" sind. Die Frage ist, ob die Adresse, die sie haben, für den Zugriff auf Ihr Programm zulässig ist. Die spezielle Adresse Null (aka null
) wird bewusst nicht in Ihren Adressraum abgebildet, sodass die Speicherverwaltungseinheit (MMU) einen Segmentierungsfehler generiert, wenn auf sie zugegriffen wird und Ihr Programm abstürzt. Da die Adresse Null jedoch absichtlich nicht zugeordnet ist, wird sie zu einem idealen Wert, der angibt, dass ein Zeiger auf nichts zeigt, daher seine Rolle als null
. Vervollständigen Sie die Geschichte, indem Sie mit new
oder Speicher zuweisenmalloc()
Das Betriebssystem konfiguriert die MMU so, dass Seiten des Arbeitsspeichers Ihrem Adressraum zugeordnet werden und diese dann verwendet werden können. Es gibt in der Regel immer noch große Adressbereiche, die nicht zugeordnet sind und daher auch zu Segmentierungsfehlern führen.
std::shared_ptr<Apple>
ist ein Beispiel, das weder GC noch LeakApple
beim Nullsetzen enthält.shared_ptr
nur eine Grundform für die Garbage Collection? GC erfordert nicht, dass es einen separaten "Garbage Collector" gibt, sondern nur, dass eine Garbage Collection stattfindet.Die Antwort hängt von der Sprache ab, die Sie verwenden.
C / C ++
In C und C ++ war das Schlüsselwort NULL, und was NULL wirklich war, war 0. Es wurde entschieden, dass "0x0000" niemals ein gültiger Zeiger auf ein Objekt sein würde, und das ist der Wert, der zugewiesen wird, um dies anzuzeigen ist kein gültiger Zeiger. Es ist jedoch völlig willkürlich. Wenn Sie versuchen, wie ein Zeiger darauf zuzugreifen, verhält es sich genauso wie ein Zeiger auf ein Objekt, das nicht mehr im Speicher vorhanden ist, wodurch eine ungültige Zeigerausnahme ausgelöst wird. Der Zeiger selbst belegt Speicher, aber nicht mehr als ein ganzzahliges Objekt. Wenn Sie also 1000 Nullzeiger haben, entspricht dies 1000 ganzen Zahlen. Wenn einige dieser Zeiger auf gültige Objekte verweisen, entspricht die Speichernutzung 1000 ganzen Zahlen plus dem in diesen gültigen Zeigern enthaltenen Speicher. Denken Sie daran, dass in C oder C ++,Es wurde kein impliziter Speicher freigegeben, daher müssen Sie dieses Objekt explizit mit dealloc (C) oder delete (C ++) löschen.
Java
Anders als in C und C ++ ist in Java null nur ein Schlüsselwort. Anstatt null wie einen Zeiger auf ein Objekt zu verwalten, wird es intern verwaltet und wie ein Literal behandelt. Dies beseitigt die Notwendigkeit, Zeiger als Integer-Typen einzubinden, und ermöglicht es Java, Zeiger vollständig zu abstrahieren. Auch wenn Java es besser verbirgt, handelt es sich dennoch um Zeiger, was bedeutet, dass 1000 Nullzeiger immer noch das Äquivalent von 1000 ganzen Zahlen verbrauchen. Offensichtlich wird, wenn sie auf Objekte verweisen, ähnlich wie in C und C ++, Speicher von diesen Objekten belegt, bis keine Zeiger mehr auf sie verweisen. In den meisten Fällen müssen Sie nicht nachverfolgen, welche Objekte freigegeben sind und welche nicht (es sei denn, Sie haben Gründe, auf Objekte schwach zu verweisen).
quelle
NULL
( übrigens kein Schlüsselwort) so behandelt, als wären sie Null-Bits. Aber sie müssen nicht als solche umgesetzt werden, und in der Tat einige obskure Implementierungen tun Verwendung nicht-Null - Null - Zeiger. Wenn ich schreibe,if (myptr == 0)
wird der Compiler das Richtige tun, auch wenn der Nullzeiger intern durch dargestellt wird0xabcdef
.0
ist eine Nullzeiger-Konstante, dies bedeutet jedoch nicht, dassmyptr == 0
überprüft wird, ob alle Bits vonmyptr
Null sind.NULL
Makro überhaupt nicht zu erwähnen , sondern über den „Nullzeiger“ zu sprechen und ausdrücklich zu erwähnen, dass „Literal-0 implizit in einen Nullzeiger konvertiert werden kann“.Ein Zeiger ist einfach eine Variable, die meist vom Typ Integer ist. Es gibt eine Speicheradresse an, unter der das eigentliche Objekt gespeichert ist.
Die meisten Sprachen erlauben den Zugriff auf Objektmitglieder über diese Zeigervariable:
Der Compiler weiß, wie er auf die Mitglieder von an zugreift
Apple
. Es "folgt" dem Zeiger aufmyApple
die Adresse und ruft den Wert von abappleInt
Wenn Sie den Nullzeiger einer Zeigervariablen zuweisen, weisen Sie den Zeiger auf keine Speicheradresse. (Dies macht den Zugang für Mitglieder unmöglich.)
Für jeden Zeiger benötigen Sie Speicher, um den Integer-Wert der Speicheradresse zu speichern (meistens 4 Bytes bei 32-Bit-Systemen, 8 Bytes bei 64-Bit-Systemen). Dies gilt auch für Nullzeiger.
quelle
Schnelles Beispiel (Notizvariablennamen werden nicht gespeichert):
Prost.
quelle