Historia de la cuestión:
La memoria de pila está presente en todas las arquitecturas principales. En el lenguaje C, las variables automáticas (locales) se colocan en la pila, proporcionando una alta velocidad de asignación y liberación de memoria en comparación con el heap dinámico.
Problema:
El uso de la pila está limitado en tamaño, las variables automáticas se destruyen automáticamente al salir del bloque, y salir del límite de la pila (desbordamiento de pila) conduce a la finalización anormal del programa o a la corrupción de datos.
Solución:
Las variables locales declaradas dentro de las funciones sin un modificador especial se colocan en la pila. Esta área de almacenamiento automático se crea al ingresar a la función y se destruye al salir. El tamaño de la pila está limitado y solo se puede cambiar mediante opciones de enlace/sistema.
Ejemplo de código:
#include <stdio.h> void foo() { int arr[100]; // colocado en la pila for (int i = 0; i < 100; ++i) arr[i] = i; printf("Primer elemento: %d\n", arr[0]); } // arr se destruye al salir de foo
Características clave:
¿Se puede devolver una variable local de la función por dirección?
No, porque la variable se destruye al salir de la función, y el "puntero colgante" resultante conduce a un comportamiento indefinido.
int* bad() { int x = 42; return &x; // error: el puntero devuelto apunta a la pila liberada }
¿Es posible colocar un gran array (por ejemplo, 1 MB) en la pila?
Para la mayoría de los sistemas, la pila está limitada (de decenas a cientos de kB). Intentar declarar grandes arrays en la pila provocará un desbordamiento de pila.
¿Cuál es la diferencia entre variables estáticas y automáticas en cuanto a la colocación?
Las variables estáticas (incluso en funciones) se colocan en el área de memoria estática, no se limpian entre llamadas, mientras que las automáticas se colocan en la pila y se destruyen al salir del bloque.
En una función para cálculos, se asignó un array de 8192*1024 double en la pila. El programa recibía SIGSEGV al ejecutarse en Linux, aunque se compilaba sin errores.
Pros:
Contras:
Para trabajar con buffers grandes se usó asignación dinámica de memoria a través de malloc/free. En la pila solo se colocaron pequeñas variables de trabajo.
Pros:
Contras: