Cuando un programa se ejecuta, los datos deben almacenarse en memoria. El espacio que ocupan los datos y su ubicación de almacenamiento se determinan por el tipo de dato. Durante la ejecución del programa se usan dos zonas de memoria para guardar información: Pila (Stack) y Montículo (Heap).
Pila (Stack)
La pila es un arreglo continuo de memoria que sigue el principio de datos Último en entrar, primero en salir (LIFO). Almacena tres tipos de información:
- Valores de variables de determinados tipos
- Contexto actual de ejecución del programa
- Parámetros que se envían a los métodos

Las operaciones de memoria de la pila son gestionadas automáticamente por el sistema, el desarrollador no necesita manipularlas manualmente. Comprender la lógica interna de la pila simplifica el análisis del flujo de ejecución y la lectura de la documentación oficial de C#.
Características principales de la pila
- Solo se pueden agregar y eliminar datos en el tope de la pila
- Guardar datos en el tope: Push (apilar)
- Extraer datos del tope: Pop (desapilar)
Propiedades de la memoria de pila
- Velocidad muy alta de asignación y liberación de memoria, usa bloques contiguos de RAM
- Ciclo de vida vinculado a la llamada de método: el marco de pila se destruye automáticamente al finalizar el método
- Almacena: variables de tipo valor, parámetros de método, variables locales, contexto de ejecución

Para entender mejor el funcionamiento del montículo, veamos un ejemplo de código sencillo
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;
}
}
Lenguaje del código: JavaScript (javascript)
La lógica de este ejemplo es muy sencilla. Desde la primera línea de la función Main, punto de entrada del programa, creamos una variable entera a, luego la variable b en la segunda línea. La tercera línea invoca la función Add enviando los valores de a y b al interior del método. x recibe el valor de a, y el valor de b; la función devuelve el resultado de x + y igual a 30 al punto de llamada para asignarlo a sum. Cuando la función Add termine de ejecutarse, x e y se desapilan, sum toma el valor 30 y el programa finaliza al concluir Main. A continuación analizamos paso a paso todo el proceso de Push y Pop en la pila.
Flujo de ejecución del programa y proceso Push/Pop de la pila





Al finalizar Add, x e y son parámetros locales de esta función, se desapilan uno tras otro para liberar espacio y garantizar el funcionamiento fluido del sistema.
Tras el Pop, x e y desaparecen, el valor 30 devuelto por Add se envía al punto de llamada para guardarse en sum.




Recuerda un punto fundamental: durante la ejecución de una función las variables se crean de arriba abajo y se apilan en orden a → b → entrada en Add → x → y. Al terminar Add, x e y se desapilan, luego se apila sum; cuando Main finaliza, las variables se eliminan en orden inverso a su creación: sum, b, a.
Montículo (Heap)
El montículo es una amplia zona de memoria destinada a asignar bloques dinámicos para almacenar objetos de datos. A diferencia de la pila, los datos del montículo se pueden agregar y borrar en cualquier orden.
El programa no puede borrar manualmente los objetos del montículo; el Recolector de Basura (GC) del CLR (Common Language Runtime) limpia automáticamente los objetos huérfanos sin referencias inaccesibles. Esto evita errores derivados de la liberación manual de memoria obligatoria en otros lenguajes.
El montículo se puede comparar con un escritorio amplio donde se pueden colocar objetos libremente. Mientras que la pila vista antes es como un tubo de monedas con un único extremo de acceso.

Flujo de recolección del GC
- El programa crea tres objetos en el montículo y mantiene referencias válidas hacia ellos
- El programa deja de usar uno de los objetos, todas sus referencias desaparecen
- El GC detecta el objeto huérfano sin referencias y libera la memoria que ocupa
- Recolección finalizada, la memoria liberada se puede asignar a nuevos objetos
Propiedades de la memoria del montículo
- Espacios de memoria discontinuos, velocidad de asignación menor que la de la pila
- Ciclo de vida no limitado por los límites de método, gestionado centralmente por el GC
- Almacena: instancias de tipos de referencia (clases, arreglos, delegados, etc.); la pila solo guarda las direcciones de memoria de los objetos del montículo
Veamos un ejemplo práctico para clarificarlo. Como comentamos antes, las variables locales de tipo primitivo se guardan en la pila, mientras que los tipos definidos por el usuario suelen residir en el montículo. Revisa el código siguiente:
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
{
//Variables miembro
private string name;
private int age;
//Constructor, se explicará más adelante
public Student(string name, int age)
{
this.name = name;
this.age = age;
}
//Método miembro
public void DisplayInfo()
{
Console.WriteLine($"Name: {name}, Age: {age}");
}
}
Lenguaje del código: JavaScript (javascript)
La ilustración siguiente muestra la estructura de almacenamiento en memoria de las cuatro variables a, b, tom y lucy dentro de Main. Al igual que en la explicación de la pila, el código se ejecuta de arriba abajo: primero se apila a, luego b. Los valores de a y b se guardan directamente en la pila.


Por ejemplo, los datos de tom están en el bloque 00001 del montículo, la pila guarda la dirección 00001 para localizar la información posteriormente.
Cuando la función Main termine su ejecución, la referencia de dirección lucy: 01010 en la pila se desapila y destruye. Solo se elimina la dirección, los datos reales del objeto en el montículo permanecen intactos. En ese momento el objeto del montículo pierde todas las referencias registradas por las variables de la pila.


Zonas de memoria
La pila y el montículo son divisiones lógicas de memoria a nivel de software, no particiones físicas del hardware.
Pila y montículo solo son separaciones lógicas definidas por el software; la memoria RAM física no cuenta con módulos hardware dedicados marcados como «zona de pila» o «zona de montículo».
La memoria RAM física solo está compuesta por chips uniformes con direcciones físicas consecutivas, no existe ningún marcador hardware que distinga la pila del montículo
El sistema operativo asigna un espacio de memoria virtual independiente a cada programa en ejecución y divide previamente esta memoria virtual en cuatro segmentos lógicos principales:
Segmento de código: Almacena las instrucciones compiladas del programa
Segmento estático global: Variables estáticas, constantes
Segmento de pila (Stack): El hilo principal y los hilos secundarios del programa disponen cada uno de un bloque de pila independiente
Segmento de montículo (Heap): Gran pool de memoria compartida para asignaciones dinámicas
La pila y el montículo que describimos aquí son únicamente zonas lógicas asignadas por el SO a cada proceso, sin aislamiento a nivel hardware entre ambos.
Pila vs Montículo