When a program runs, data must be loaded into memory. The space data occupies and its storage location are determined by its data type. Two memory regions are used to hold runtime data: Stack and Heap.
Stack
The stack is a contiguous memory array built around the LIFO (Last In, First Out) data structure. It stores three categories of data:
- Values of certain variable types
- The current execution context of the program
- Parameters passed into methods

Memory operations on the stack are fully automated by the system; developers never need to manage them manually. Grasping the underlying mechanics of the stack makes it far easier to follow program execution flow and read the official C# documentation.
Core Properties of the Stack
- Data can only be inserted or removed at the stack top
- Writing data to the stack top: Push
- Retrieving data from the stack top: Pop
Characteristics of Stack Memory
- Extremely fast allocation and release, backed by contiguous memory blocks
- Lifetime tied to method calls: stack frames are automatically destroyed once the method finishes executing
- Stores: value-type variables, method parameters, local variables, execution context

Let’s walk through a straightforward code sample to better understand how the heap operates
class Program
{
static void Main(string[] args)
{
int a = 10;
int b = 20;
int sum = Add(a, b);
}
static int Add(int x, int y)
{
return x + y;
}
}
Code language: JavaScript (javascript)
This sample is fairly simple. Starting from the first line of the entry point Main, we declare an integer variable a, then create variable b on the second line. The third line invokes the Add function and passes the values of a and b into it. Inside Add, x holds the value of a while y holds the value of b. The function returns the sum of x and y, which evaluates to 30 and gets sent back to the caller to assign to sum. Once Add completes, x and y are popped off the stack, sum becomes 30, and after Main finishes, the program exits. We’ll break down each step below to show how the stack handles this full workflow.
Program execution flow & push/pop stack process





After Add finishes, x and y are local parameters belonging to Add and must be popped in sequence to free stack space and maintain smooth system performance.
Once popped, x and y cease to exist. The returned value 30 is delivered back to the caller to assign to sum.




Keep this rule in mind: variables are pushed top-to-bottom as functions execute. Our workflow order goes a → b → enter Add → x → y, then Add terminates with x and y popped, followed by pushing sum. When Main exits, sum, b and a are popped in reverse creation order.
The Heap
The heap is a large memory region allocated to store data objects. Unlike the stack, objects on the heap can be added and deleted in any arbitrary order.
Programs cannot manually delete heap objects. The CLR (Common Language Runtime) includes a built-in Garbage Collector (GC) that automatically cleans up orphaned heap objects with no active references. This eliminates error-prone manual memory release required in many other programming languages.
The heap can be visualized as a large desk where you can place items anywhere freely. By contrast, the stack resembles the coin tube we covered earlier, restricted to single-end access only.

GC Collection Workflow
- The program instantiates three heap objects and holds active references to each
- The program stops using one object, severing all references to it
- The GC detects the unreferenced orphan object and releases its occupied memory
- Collection completes; freed memory becomes available to allocate new objects
Characteristics of Heap Memory
- Non-contiguous memory blocks; allocation speed slower than the stack
- Lifetime independent of method scope, centrally managed by the GC
- Stores: reference-type instances (classes, arrays, delegates, etc.); the stack only stores memory address pointers pointing to heap objects
Let’s examine another example to demonstrate this clearly. As covered earlier, local primitive value-type variables reside on the stack, while custom user-defined types are allocated on the heap. See the sample below:
class Program
{
static void Main(string[] args)
{
int a = 10;
int b = 20;
Student tom = new Student("Tom", 12);
Student lucy = new Student("Lucy", 12);
}
}
class Student
{
// Member fields
private string name;
private int age;
// Constructor, covered in later chapters
public Student(string name, int age)
{
this.name = name;
this.age = age;
}
// Member method
public void DisplayInfo()
{
Console.WriteLine($"Name: {name}, Age: {age}");
}
}
Code language: JavaScript (javascript)
The following diagram illustrates memory storage for the four variables a, b, tom and lucy inside Main. Execution proceeds top-down: a gets pushed to the stack first, followed by b. The raw values of a and b are stored directly within stack memory.


In this example, tom’s data resides in heap block 00001, and the stack holds the address 00001 to locate the object data later.
Once Main finishes executing, the address pointer lucy: 01010 is popped off the stack and destroyed. Crucially, only the address reference is removed—not the actual object data stored on the heap. At this point, the heap object loses all stack-based references tracking its memory location.


Memory Segments Overview
Stack and Heap are logical memory divisions implemented at software level, not physical hardware partitions.
Stack and Heap represent purely logical memory splits managed by software; physical RAM hardware contains no dedicated hardware modules labeled “stack area” or “heap area”.
Physical RAM sticks only consist of uniform memory chips with sequential physical addresses, with no built-in markers distinguishing stack versus heap regions.
The operating system allocates an isolated virtual memory address space for every running process, pre-splitting this virtual memory into four core logical segments:
Code Segment: Stores compiled program instructions
Global Static Segment: Holds static variables and constant values
Stack Segment: Each main thread and child thread of the process gets its own independent stack memory block
Heap Segment: A large shared memory pool for dynamic memory allocation
The Stack and Heap discussed here are purely logical regions assigned by the OS to each process; there exists no hardware-level isolation between them.
Stack vs Heap