Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I want to learn about null values or null references.

For example I have a class called Apple and I created an instance of it.

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

Then I ate that apple and now it needs to be null, so I set it as null.

myApple = null;

After this call, I forgot that I ate it and now want to check.

bool isEaten = (myApple == null);

With this call, where is myApple referencing? Is null a special pointer value? If so, if I have 1000 null objects, do they occupy 1000 object memory space or 1000 int memory space if we think a pointer type as int?

share|improve this question
add comment

4 Answers

up vote 36 down vote accepted

In your example myApple has the special value null (typically all zero bits), and so is referencing nothing. The object that it originally referred to is now lost on the heap. There is no way to retrieve its location. This is known as a memory leak on systems without garbage collection.

If you originally set 1000 references to null, then you have space for just 1000 references, typically 1000 * 4 bytes (on a 32-bit system, twice that on 64). If those 1000 references originally pointed to real objects, then you allocated 1000 times the size of each object, plus space for the 1000 references.

In some languages (like C and C++), pointers always point to something, even when "uninitialized". The issue is whether the address they hold is legal for your program to access. The special address zero (aka null) is deliberately not mapped into your address space, so a segmentation fault is generated by the memory management unit (MMU) when it is accessed and your program crashes. But since address zero is deliberately not mapped in, it becomes an ideal value to use to indicate that a pointer is not pointing to anything, hence its role as null. To complete the story, as you allocate memory with new or malloc(), the operating system configures the MMU to map pages of RAM into your address space and they become usable. There are still typically vast ranges of address space that are not mapped in, and so lead to segmentation faults, too.

share|improve this answer
    
Very good explanation. –  Emmad Kareem May 8 '12 at 9:23
5  
It's slightly wrong on the "memory leak" part. It's a memory leak in systems without automatic memory management. However, GC isn't the only possible way to implemement automatic memory management. C++'s std::shared_ptr<Apple> is an example that's neither GC nor leaks the Apple when zeroed. –  MSalters May 8 '12 at 11:21
    
@MSalters - Isn't shared_ptr just a basic form for garbage collection? GC doesn't require that there be a separate "garbage collector", only that garbage collection occurs. –  Brendan Long May 8 '12 at 16:16
4  
@Brendan: The term "garbage collection" is almost universally understood to refer to non-deterministic collection that takes place independent of the normal code path. Deterministic destruction based on reference counting is something completely different. –  Mason Wheeler May 8 '12 at 17:12
add comment

The answer depends on the language you're using.

C/C++

In C and C++, the keyword was NULL, and what NULL really was was 0. It was decided that "0x0000" was never going to be a valid pointer to an object, and so that is the value which gets assigned to indicate that it is not a valid pointer. However, it's completely arbitrary. If you attempted to access it like a pointer, it would behave exactly like a pointer to an object which no longer exists in memory, causing a invalid pointer exception to be thrown. The pointer itself occupies memory, but no more than an integer object would. Hence, if you have 1000 null pointers, it is the equivalent of 1000 integers. If some of those pointers point to valid objects, then the usage of memory would be the equivalent of 1000 integers plus the memory contained in those valid pointers. Remember that in C or C++, if a pointer no longer points to its object, that does not imply memory has been released, so you must explicitly delete that object using dealloc (C) or delete (C++).

Java

Unlike in C and C++, in Java null is merely a keyword. Rather than managing null like a pointer to an object, it is managed internally and treated like a literal. This eliminated the need to tie in pointers as integer types and allows Java to abstract away pointers entirely. However even if Java hides it better, they are still pointers, meaning 1000 null pointers still consume the equivalent of 1000 integers. Obviously when they point to objects, much like C and C++, memory is consumed by those objects until no more pointers reference them, however unlike in C and C++, the garbage collector picks up on it on its next pass and frees up the memory, without requiring that you have to keep track of what objects are freed up and which objects are not, in most cases (unless you have reasons to weakly reference objects for example).

share|improve this answer
8  
Your distinction isn’t correct: in fact, in C and C++, the null pointer doesn’t need to point to the memory address 0 at all (although this is the natural implementation, same as in Java and C#). It can point literally anywhere. This is slightly confounded by the fact that literal-0 can be implicitly converted to a null pointer. But the bit pattern stored for a null pointer still need not be all zeros. –  Konrad Rudolph May 8 '12 at 11:52
    
@KonradRudolph, true, NULL was supposed to be an abstraction of sorts, however if NULL ever happened to correspond with an actual valid pointer, you'd end up testing if a pointer was NULL and having it return true! NULL would have to be another invalid pointer value, if it weren't NULL. And when you consider that a non-zero value would allow you to enter clauses like if(NULL), anything other than zero seems rather non-intuitive. –  Neil May 8 '12 at 12:28
2  
@Neil: a null pointer constant (prvalue of integer type that evaluates to zero) is convertible to a null pointer value. (§4.10 C++11.) A null pointer value is not guaranteed to have all bits zero. 0 is a null pointer constant, but this doesn't mean that myptr == 0 checks if all the bits of myptr are zero. –  Mat May 8 '12 at 13:43
5  
@Neil: You might want to check this entry in the C faq or this SO question –  hugomg May 8 '12 at 14:21
1  
@Neil That’s why I took pains not to mention the NULL macro at all, rather talking about the “null pointer”, and explicitly mentioning that “literal-0 can be implicitly converted to a null pointer”. –  Konrad Rudolph May 8 '12 at 14:32
show 11 more comments

A pointer is simply a variable which is mostly of an integer type. It specifies a memory address where the actual object is stored.

Most languages allow to access object members via this pointer variable:

int localInt = myApple.appleInt;

The compiler knows how to access the members of an Apple. It "follows" the pointer to myApple's address and retrieves the value of the appleInt

If you assign the null pointer to a pointer variable, you make the pointer point to no memory address. (Which makes member access impossible.)

For every pointer you need memory to hold the memory address integer value (mostly 4 Bytes on 32 bit systems, 8 bytes on 64 bit systems). This is also true for null pointers.

share|improve this answer
    
I think the reference variables/objects aren't exactly pointers . If you print them they contain ClassName@Hashcode . JVM internally uses Hashtable to store Hashcode with actual address and uses a Hash Algorithm to retrieve the actual address when necessary . –  minusSeven May 8 '12 at 8:18
    
@minusSeven That's correct for what concerns literal objects like integers. Otherwise the hashtable holds pointers to other objects contained within the Apple class itself. –  Neil May 8 '12 at 8:27
    
@minusSeven: I agree. The details of pointer implementation depend heavily on the language/runtime. But I think those details are not that relevant for the specific question. –  Stephan May 8 '12 at 8:29
add comment

Quick example (note varible names are not stored):

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


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

Cheers.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.