Boş değerler nerede saklanıyor ya da hiç saklanıyorlar mı?


39

Boş değerler veya boş referanslar hakkında bilgi edinmek istiyorum.

Örneğin Apple adında bir sınıfım var ve bunun bir örneğini oluşturdum.

Apple myApple = new Apple("yummy"); // The data is stored in memory

Sonra o elmayı yedim ve şimdi null olması gerekiyor, ben de null olarak ayarlıyorum.

myApple = null;

Bu çağrıdan sonra, onu yediğimi ve kontrol etmek istediğimi unuttum.

bool isEaten = (myApple == null);

Bu çağrı ile benim Uygulamam nereye başvuruyor? Boş özel bir işaretçi değeri var mı? Öyleyse, 1000 boş nesneye sahipsem, bir işaretçi türünü int olarak düşünürsek 1000 nesne boşluğu veya 1000 int boş hafıza alanı kaplar mı?

Yanıtlar:


45

Örneğinizde myAppleözel bir değer null(tipik olarak tüm sıfır bitler) var ve bu nedenle hiçbir şeyden bahsetmiyoruz. Başlangıçta bahsettiği nesne şimdi öbek üzerinde kaybolur. Konumunu almanın bir yolu yok. Bu, çöp toplama sistemlerinde bellek sızıntısı olarak bilinir.

Başlangıçta 1000 referansı null değerine ayarlarsanız, sadece 1000 referans, genellikle 1000 * 4 bayt (32-bit bir sistemde, 64'ün iki katı) için alanınız vardır. Bu 1000 referans başlangıçta gerçek nesnelere işaret ediyorsa, o zaman her nesnenin boyutunun 1000 katını artı 1000 referans için alan ayırdınız.

Bazı dillerde (C ve C ++ gibi), işaretçiler her zaman "başlatılmamış" olsa bile bir şeyi işaret eder. Sorun, sahip oldukları adresin programınızın erişmesi için yasal olup olmadığıdır. Özel adres sıfır (aka null), adres alanınıza kasten eşlenmez, bu nedenle erişildiğinde ve programınız çöktüğünde, bellek yönetim birimi (MMU) tarafından bir bölümleme hatası oluşturulur. Adres sıfır kasten beri Ama değil haritalandaı ideal bir değer, bir işaretçi, bir şey olarak dolayısıyla rolünü işaret olmadığını belirtmek için kullanmak olur null. Hikayeyi tamamlamak için, ile newveyamalloc()işletim sistemi, MMU’yu RAM sayfalarını adres alanınıza eşlemek için yapılandırır ve kullanılabilir hale gelir. Hala tipik olarak, eşlenmemiş çok fazla adres alanı aralığı vardır ve bu nedenle de bölümlendirme hatalarına neden olur.


Çok iyi açıklama.
NoChance

6
"Bellek sızıntısı" bölümünde biraz yanlış. Otomatik bellek yönetimi olmayan sistemlerde bellek sızıntısı var. Ancak, otomatik bellek yönetimini gerçekleştirmenin tek yolu GC değildir. C ++ 'lar std::shared_ptr<Apple>ne GC ne de Applesıfırlandığı zaman sızıntı yapan bir örnektir .
MSalters

1
@ MSalters - shared_ptrÇöp toplama için sadece temel bir form değil mi? GC, ayrı bir "çöp toplayıcı" olmasını gerektirmez, yalnızca bu çöp toplama işlemi gerçekleşir.
Monica'yı

5
@Brendan: "Çöp toplama" terimi, genel olarak normal kod yolundan bağımsız olarak yer alan deterministik olmayan koleksiyona atıfta bulunur. Referans sayımına dayalı deterministik yıkım tamamen farklı bir şeydir.
Mason Wheeler

1
İyi açıklama. Hafifçe yanıltıcı noktalardan biri, hafıza tahsisatının RAM ile eşleştiği varsayımıdır. RAM, kısa süreli bellek depolama için bir mekanizmadır, ancak gerçek depolama mekanizması işletim sistemi tarafından soyutlanır. Windows'ta (halka sıfır olmayan uygulamalar için) bellek sayfaları sanallaştırılır ve RAM, disk takas dosyası ya da belki başka bir depolama aygıtıyla eşlenebilir.
Simon Gillbee

13

Cevap, kullandığınız dile bağlıdır.

C / C ++

C ve C ++ 'da, anahtar kelime NULL ve NULL' ın gerçekte 0 olduğu şeydi. "0x0000" öğesinin hiçbir zaman bir nesneye geçerli bir işaretçi olmayacağına karar verildi ve bu nedenle, bunu belirtmek için atanan değer bu oldu. geçerli bir işaretçi değil. Ancak, tamamen keyfi. Bir işaretçi gibi erişmeye çalıştıysanız, tam olarak bellekte bulunmayan bir nesneye bir işaretçi gibi davranarak geçersiz bir işaretçi istisnasının atılmasına neden olur. İşaretçinin kendisi hafızayı kaplar, ancak bir tamsayı nesnesinden daha fazla değildir. Dolayısıyla, 1000 boş işaretleyiciniz varsa, 1000 tam sayıya eşdeğerdir. Bu işaretçilerden bazıları geçerli nesnelere işaret ediyorsa, o zaman hafıza kullanımı 1000 tam sayıya ve bu geçerli işaretçilerde bulunan hafızaya eşdeğer olacaktır. Unutma, C veya C ++değil açıkça (C ++) bu nesne kullanılarak dealloc (C) silmek veya silmeniz gerekir böylece bellek, serbest bırakıldı ima.

Java

C ve C ++ 'dan farklı olarak, Java'da null sadece bir anahtar kelimedir. Bir nesneye bir işaretçi gibi null yönetmek yerine, dahili olarak yönetilir ve değişmez gibi davranılır. Bu, işaretçilere tam sayı türleri olarak bağlanma gereksinimini ortadan kaldırır ve Java'nın işaretçileri tamamen soyutlamasına olanak tanır. Bununla birlikte, Java daha iyi gizlese bile, hala göstericilerdir, yani 1000 sıfır işaretçi hala 1000 tam sayıya eşdeğer tüketir. Açıkça görülüyor ki, C ve C ++ gibi nesnelere işaret ettikleri zaman, bu nesneler tarafından daha fazla işaretçi atıfta bulunmadıkça bellek tüketiliyor, ancak C ve C ++ 'dan farklı olarak, çöp toplayıcı onu bir sonraki geçişte alır ve belleği boşaltır. hangi durumlarda serbest bırakıldığını ve hangi nesnelerin olmadıklarını takip etmenize gerek kalmadan, çoğu durumda (örneğin nesnelere zayıf bir şekilde başvuruda bulunma nedenleriniz olmadığı sürece).


9
Farklılığınız doğru değil: aslında, C ve C ++ 'da, boş göstericinin hiç bellek adresini 0 göstermesi gerekmez (bu, Java ve C #' da olduğu gibi doğal bir uygulama olmasına rağmen). Kelimenin tam anlamıyla herhangi bir yere işaret edebilir. Bu, değişmez-0 öğesinin örtük olarak bir boş göstericiye dönüştürülebilmesi gerçeğinden dolayı biraz karışıktır. Ancak boş bir işaretçi için depolanan bit deseninin hala sıfır olması gerekmez.
Konrad Rudolph

1
Hayır hatalısın. Anlambilim tamamen saydamdır… programda boş işaretçiler ve makro NULL( bu arada bir anahtar kelime değil) sıfır bitmiş gibi ele alınır. Ama örneğin uygulanması gereken ve aslında bazı karanlık uygulamalar yok do kullanım sıfır olmayan boş işaretçileri. Eğer if (myptr == 0)yazarsam, boş gösterici dahili olarak temsil edilse bile, derleyici doğru olanı yapacaktır 0xabcdef.
Konrad Rudolph

3
@Neil: boş bir işaretçi sabiti (sıfıra göre değerlendirilen tamsayı türünün değeri) boş bir işaretçi değerine dönüştürülebilir . (§4.10 C ++ 11.) Boş bir işaretçi değerinin tüm bitlerin sıfır olması garanti edilmez. 0bir boş gösterici sabitidir, ancak bu, myptr == 0tüm bitlerin myptrsıfır olup olmadığını kontrol ettiği anlamına gelmez .
Mat,

5
@Neil: Bu girişi C sss veya SO sorusundaki bu soruyu kontrol etmek isteyebilirsiniz
hugomg

1
@Neil Bu yüzden NULLmakroyu hiç belirtmemek, “boş gösterici” hakkında konuşmaktan ve açıkça “sıfır-0'ın boş gösterici haline getirilebileceğinden” bahsetmekten acı çektim .
Konrad Rudolph

5

Bir işaretçi, çoğunlukla bir tamsayı tipi olan bir değişkendir. Gerçek nesnenin depolandığı bir hafıza adresini belirtir.

Çoğu dil bu işaretçi değişkeni ile nesne üyelerine erişime izin verir:

int localInt = myApple.appleInt;

Derleyici bir üyelerine nasıl erişileceğini bilir Apple. İmleci myAppleadrese gönderir ve değerini alır.appleInt

Boş işaretçiyi bir işaretçi değişkenine atarsanız, işaretçiyi işaretlenmemiş bellek adresine işaret etmezsiniz. (Bu üye erişimini imkansız kılar.)

Her işaretçi için, bellek adresi tamsayı değerini tutmak için belleğe ihtiyacınız vardır (32 bit sistemlerde çoğunlukla 4 Bayt, 64 bit sistemlerde 8 bayt). Bu aynı zamanda boş işaretçiler için de geçerlidir.


Referans değişkenleri / nesneleri tam olarak işaretçiler olmadığını düşünüyorum. Bunları yazdırırsanız, ClassName @ Hashcode içerirler. JVM dahili olarak Hashcode'u gerçek adresle saklamak için Hashtable'ı kullanır ve gerektiğinde gerçek adresi almak için bir Hash Algoritması kullanır.
eksiSeven

@ minusSeven Tamsayılar gibi gerçek nesnelerle ilgili olanlar için bu doğru. Aksi takdirde, karma tablo, Apple sınıfının içinde bulunan diğer nesnelere işaretçiler içerir.
Neil,

@ minusSeven: Katılıyorum. İşaretçi uygulamasının ayrıntıları, büyük ölçüde dile / çalışma zamanına bağlıdır. Ancak bu ayrıntıların belirli bir soruyla alakalı olmadığını düşünüyorum.
Stephan

4

Hızlı örnek (değişken isimlerin kaydedilmediğine dikkat edin):

void main()
{
  int X = 3;
  int *Y = X;
  int *Z = null;
} // void main(...)


...........................
....+-----+--------+.......
....|     |   X    |.......
....+-----+--------+.......
....| 100 |   3    |<---+..
....+-----+--------+....|..
........................|..
....+-----+--------+....|..
....|     |   Y    |....|..
....+-----+--------+....|..
....| 102 |  100   +----+..
....+-----+--------+.......
...........................
....+-----+--------+.......
....|     |   z    |.......
....+-----+--------+.......
....| 104 |   0    |.......
....+-----+--------+.......
...........................

Şerefe.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.