Dove sono memorizzati i valori nulli o sono memorizzati?

36

Voglio conoscere i valori nulli oi riferimenti null.

Ad esempio, ho una classe chiamata Apple e ne ho creato un'istanza.

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

Poi ho mangiato quella mela e ora deve essere nullo, quindi l'ho impostato come null.

myApple = null;

Dopo questa chiamata, ho dimenticato di averlo mangiato e ora voglio controllare.

bool isEaten = (myApple == null);

Con questa chiamata, dove si trova myApple referencing? Null è un valore puntatore speciale? In tal caso, se ho 1000 oggetti null, occupano 1000 spazio di memoria dell'oggetto o 1000 spazio di memoria int se pensiamo che un puntatore tipo int?

    
posta Mert Akcakaya 08.05.2012 - 09:31
fonte

4 risposte

43

Nel tuo esempio myApple ha il valore speciale null (tipicamente tutti i bit zero), quindi non fa riferimento a nulla. L'oggetto a cui si riferiva originariamente è ora perso nell'heap. Non c'è modo di recuperare la sua posizione. Questo è noto come perdita di memoria su sistemi senza garbage collection.

Se inizialmente hai impostato 1000 riferimenti a null, allora hai spazio solo per 1000 riferimenti, in genere 1000 * 4 byte (su un sistema a 32 bit, due volte su 64). Se quei 1000 riferimenti puntavano originariamente su oggetti reali, allora hai assegnato 1000 volte la dimensione di ogni oggetto, più lo spazio per i 1000 riferimenti.

In alcuni linguaggi (come C e C ++), i puntatori sempre indicano qualcosa, anche quando "non inizializzato". Il problema è se l'indirizzo che ritengono sia legale perché il tuo programma acceda. Lo zero indirizzo speciale (alias null ) non viene deliberatamente mappato nello spazio degli indirizzi, quindi un errore di segmentazione viene generato dall'unità di gestione della memoria (MMU) quando si accede e il programma si blocca. Ma poiché l'indirizzo zero è deliberatamente non mappato, diventa un valore ideale da utilizzare per indicare che un puntatore non punta a nulla, quindi il suo ruolo come null . Per completare la storia, quando si assegna memoria con new o malloc() , il sistema operativo configura la MMU per mappare le pagine della RAM nello spazio degli indirizzi e diventano utilizzabili. Ci sono ancora tipicamente vasti intervalli di spazio degli indirizzi che non sono mappati, e quindi portano anche a errori di segmentazione.

    
risposta data 08.05.2012 - 09:46
fonte
13

La risposta dipende dalla lingua che stai utilizzando.

C / C ++

In C e C ++, la parola chiave era NULL e ciò che NULL era realmente era 0. Si decise che "0x0000" non sarebbe mai stato un puntatore valido per un oggetto, e quindi questo è il valore che viene assegnato a indica che non è un puntatore valido. Tuttavia, è completamente arbitrario. Se si è tentato di accedervi come un puntatore, si comporterebbe esattamente come un puntatore a un oggetto che non esiste più in memoria, causando un'eccezione di puntatore non valida. Il puntatore stesso occupa la memoria, ma non più di un oggetto intero. Quindi, se hai 1000 puntatori nulli, è l'equivalente di 1000 numeri interi. Se alcuni di questi puntatori puntano a oggetti validi, l'utilizzo della memoria sarebbe l'equivalente di 1000 numeri interi più la memoria contenuta in quei puntatori validi. Ricorda che in C o C ++, se un puntatore non punta più al suo oggetto, che non implica che la memoria è stata rilasciata, quindi devi eliminare esplicitamente quell'oggetto usando dealloc (C) o delete (C ++) .

Java

Diversamente da C e C ++, in Java null è semplicemente una parola chiave. Piuttosto che gestire null come un puntatore a un oggetto, è gestito internamente e trattato come un letterale. Ciò ha eliminato la necessità di collegare i puntatori come tipi interi e consente a Java di astrarre completamente i puntatori. Tuttavia, anche se Java lo nasconde meglio, sono ancora puntatori, ovvero 1000 puntatori nulli consumano ancora l'equivalente di 1000 interi. Ovviamente quando puntano agli oggetti, proprio come C e C ++, la memoria viene consumata da quegli oggetti fino a quando non vi sono più puntatori che li fanno riferimento, tuttavia diversamente da C e C ++, il garbage collector preleva su di esso al passaggio successivo e libera la memoria, senza che sia necessario tenere traccia di quali oggetti sono stati liberati e quali non sono, nella maggior parte dei casi (a meno che non si abbiano motivi per fare riferimento ad oggetti debolmente, ad esempio).

    
risposta data 08.05.2012 - 10:13
fonte
5

Un puntatore è semplicemente una variabile che è per lo più di un tipo intero. Specifica un indirizzo di memoria in cui è archiviato l'oggetto reale.

La maggior parte delle lingue consente di accedere ai membri dell'oggetto tramite questa variabile puntatore:

int localInt = myApple.appleInt;

Il compilatore sa come accedere ai membri di Apple . "Segue" il puntatore all'indirizzo myApple e recupera il valore di appleInt

Se assegni il puntatore nullo a una variabile puntatore, il puntatore non punta a nessun indirizzo di memoria. (Il che rende impossibile l'accesso ai membri.)

Per ogni puntatore è necessario che la memoria contenga il valore intero dell'indirizzo di memoria (principalmente 4 byte su sistemi a 32 bit, 8 byte su sistemi a 64 bit). Questo vale anche per i puntatori nulli.

    
risposta data 08.05.2012 - 09:55
fonte
4

Esempio rapido (i nomi varible non sono memorizzati):

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


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

Saluti.

    
risposta data 08.05.2012 - 22:11
fonte

Leggi altre domande sui tag