The stack is a data structure in memory used for storing items in a last-in-first-out manner (LIFO).The stack contains both local variable and stack call. It also stores the references of objects that are stored on heap.
The heap or managed heap is data structure in memory where all objects-reference types-are stored. When an object is instantiated, the object is stored on the heap as a block of data containing its data members. Then, the memory address of the block is stored in reference variable. Future references to the object are through the reference variables.
Now we discuss about stack memory and heap memory.There are two places, C#, JAVA or any object-based language stores items in memory as your code executes. Both the Stack and Heap help us run our code. They reside in the operating memory on our machine and contain the pieces of information we need to make it all happen.
When we declare a variable in C#, JAVA, or any object based language, compiler allocates some chunk of memory in the RAM. This memory has three things: the name of a variable, the data type of a variable, the value of a variable.
That was a simple explanation of what happens in memory. But memory is allocated depending on the data type of variable. There are two types of memory allocation: stack memory and heap memory.
When we call a method in any object-based language, it’s all local variables are created on the top of stack-creating it’s so called stack frame. When the method executes, it has access to only its local variables i.e. its environment is limited to the data on the stack frame.
If the method calls another method then the new method creates its stack frame on the top of the stack. In this way, each new method can allocate its own variables in its own portion of the memory allocated to the stack.
The beauty of stack allocation is that to implement garbage disposal all that has to happen is that when each method terminates its simply clears the stack of its stack frame i.e. it adjusts the stack pointer to point to the end of its stack frame so returning the memory to use.Of course when a method ends control returns to the method that called it and it finds the stack in just the state it needs to access its own local variables.
Now, i explain example about stack memory, what actually happens in below code internally.
Public void method1()
Class1 cls1=new Class1();
It’s a three line code; let’s understand line by line how things execute internally.
- Line 1: When this line is executed, the compiler allocates a small amount of memory in the stack. The stack is responsible for keeping track of the running memory needed in your application.
- Line 2: Now the execution moves to the next step. As the name says stack, it stacks this memory allocation on top of the first memory allocation. You can think about stack as a series of compartments or boxes put on top of each other.
Memory allocation and de-allocation is done using LIFO (Last In First Out) logic. In other words memory is allocated and de-allocated at only one end of the memory, i.e., top of the stack.
The stack works well for storing all manner of data that is created and destroyed following the pattern of method calls – but for global data and for very large or complex data we need something else.
- Line 3: In line 3, we have created an object. When this line is executed it creates a pointer on the stack and the actual object is stored in a different type of memory location called ‘Heap’. ‘Heap’ does not track running memory; it’s just a pile of objects which can be reached at any moment of time. Heap is used for dynamic memory allocation.
One more important point to note here is reference pointers are allocated on stack. The statement, Class1 cls1; does not allocate memory for an instance of Class1, it only allocates a stack variable cls1 (and sets it to null). The time it hits the new keyword, it allocates on “heap”.
Exiting the method (the fun): Now finally the execution control starts exiting the method. When it passes the end control, it clears all the memory variables which are assigned on stack. In other words all variables which are related toint data type are de-allocated in ‘LIFO’ fashion from the stack.
The big catch – It did not de-allocate the heap memory. This memory will be later de-allocated by the garbage collector.
When this method terminates the reference of object cls1 is also destroyed, which is stored in heap memory.Now the reference of object is disappeared ,which creates redundant problem.
To overcome this problem,garbage collector is used ,which keeps track of what is stored on the heap and how many references there are to each.When an object on the heap has no references to it then it is deallocated and the memory recovered.
Now many of our developer friends must be wondering why two types of memory, can’t we just allocate everything on just one memory type and we are done?
If you look closely, primitive data types are not complex, they hold single values like ‘int i = 0’. Object data types are complex, they reference other objects or other primitive data types. In other words, they hold reference to other multiple values and each one of them must be stored in memory. Object types need dynamic memory while primitive ones needs static type memory. If the requirement is of dynamic memory, it’s allocated on the heap or else it goes on a stack.
The following table summarizes the differences between stack and heap:
|Memory||Contents||Item Order||Item Life Time||ItemRemoval||Timing|
|Stack||Value types, Stack frames||Sequential(LIFO)||Scope||Pop||deterministic|
|Heap||Objects||Random||Reference count||Garbage Collection||Nondeterministic|