
En las arquitecturas informáticas, las pilas son regiones de memoria donde se agregan o eliminan datos siguiendo el principio de último en entrar, primero en salir (LIFO, por sus siglas en inglés) .
En la mayoría de los sistemas informáticos modernos, cada hilo tiene una región de memoria reservada, denominada pila. Cuando una función se ejecuta, puede añadir parte de sus datos de estado local a la parte superior de la pila; al finalizar, la función es responsable de eliminar esos datos de la pila. Como mínimo, la pila de un hilo se utiliza para almacenar la dirección de retorno proporcionada por quien realiza la llamada, lo que permite que las instrucciones de retorno apunten a la ubicación correcta.
La pila se usa frecuentemente para almacenar variables de longitud fija locales a las funciones activas. Los programadores también pueden optar por usar la pila explícitamente para almacenar datos locales de longitud variable. Si una región de memoria se encuentra en la pila del hilo, se dice que esa memoria se ha asignado en la pila, es decir, asignación de memoria basada en la pila (SBMA). Esto contrasta con la asignación de memoria basada en el montón (HBMA). La SBMA suele estar estrechamente vinculada a una pila de llamadas a funciones .
Ventajas y desventajas
Debido a que los datos se agregan y se eliminan de manera última en entrar, primera en salir, la asignación de memoria basada en pila es muy simple y normalmente mucho más rápida que la asignación de memoria basada en montón (también conocida como asignación de memoria dinámica ), por ejemplo , la de C.malloc
Otra característica es que la memoria en la pila se recupera automáticamente y de forma muy eficiente cuando la función finaliza, lo que puede resultar conveniente para el programador si los datos ya no son necesarios. [ 1 ] (Lo mismo se aplica a longjmp si se movió a un punto antes de que allocaocurriera la llamada). Sin embargo, si los datos deben conservarse de alguna forma, entonces deben copiarse de la pila al montón antes de que la función finalice. Por lo tanto, la asignación basada en la pila es adecuada para datos temporales o datos que ya no se requieren después de que la función actual finalice.
El tamaño de pila asignado a un hilo puede ser tan pequeño como unos pocos bytes en algunas CPU pequeñas. Asignar más memoria en la pila de la disponible puede provocar un fallo debido a un desbordamiento de pila . Esta es también la razón por la que las funciones que utilizan allocase suelen impedir que se inserten en línea: [ 2 ] si una función de este tipo se insertara en línea en un bucle, quien la llama sufriría un aumento inesperado en el uso de la pila, lo que haría que un desbordamiento fuera mucho más probable.
La asignación basada en pila también puede causar problemas menores de rendimiento: conduce a marcos de pila de tamaño variable, por lo que es necesario gestionar tanto los punteros de pila como los de marcomalloc (con marcos de pila de tamaño fijo, el puntero de pila es redundante debido a que se multiplica el puntero de marco de pila por el tamaño de cada marco). Esto suele ser mucho menos costoso que llamar a y freede todos modos. En particular, si la función actual contiene tanto llamadas a allocacomo bloques que contienen datos locales de longitud variable, entonces se produce un conflicto entre los intentos de alloca de aumentar el marco de pila actual hasta que la función actual finaliza frente a la necesidad del compilador de colocar variables locales de longitud variable en la misma ubicación en el marco de pila. Este conflicto se resuelve normalmente creando una cadena separada de almacenamiento en el montón para cada llamada a alloca. [ 3 ] La cadena registra la profundidad de la pila en la que se produce cada asignación, las llamadas subsiguientes a allocaen cualquier función recortan esta cadena a la profundidad de pila actual para eventualmente (pero no inmediatamente) liberar cualquier almacenamiento en esta cadena. Una llamada a allocacon un argumento de cero también se puede utilizar para activar la liberación de memoria sin asignar más memoria de ese tipo. Como consecuencia de este conflicto entre allocay el almacenamiento de variables locales, usar allocapodría no ser más eficiente que usar malloc.
Interfaz del sistema
Muchos sistemas tipo Unix, así como Microsoft Windows, implementan una función allocapara asignar dinámicamente memoria de pila de forma similar a la basada en el montón malloc. Un compilador normalmente la traduce a instrucciones en línea que manipulan el puntero de pila, de forma similar a como se manejan los arreglos de longitud variable . [ 4 ] Aunque no es necesario liberar explícitamente la memoria, existe el riesgo de un comportamiento indefinido debido al desbordamiento de pila. [ 5 ] La función estaba presente en los sistemas Unix ya en 32/V (1978), pero no forma parte del estándar C ni de ningún estándar POSIX .
Existe una versión más segura allocallamada _malloca, que asigna en el montón si el tamaño de asignación es demasiado grande e informa errores de desbordamiento de pila, en Microsoft Windows. Requiere el uso de _freea. [ 6 ] gnulib proporciona una interfaz equivalente, aunque en lugar de lanzar una excepción SEH en caso de desbordamiento, delega a malloccuando se detecta un tamaño demasiado grande. [ 7 ] Se puede emular una característica similar utilizando contabilidad manual y comprobación de tamaño, como en los usos de alloca_accounten glibc. [ 8 ]
Algunas familias de procesadores, como la x86 , tienen instrucciones especiales para manipular la pila del hilo que se está ejecutando. Otras familias de procesadores, como RISC-V , PowerPC y MIPS , no tienen soporte explícito para la pila, sino que se basan en convenciones y delegan la gestión de la pila a la interfaz binaria de aplicación (ABI) del sistema operativo.
VLAs de automóviles
Además, desde la versión C99 de C (opcional desde C11), es posible crear un array en la pila dentro de una función, automáticamente, conocido como auto VLA ( array de longitud variable ). [ 9 ] Sin embargo, no es compatible con C++ . [ 10 ]
void f ( int len ) { // auto VLA: la longitud de este array se establece en // el momento de la invocación de la función / generación de la pila. int b [ len ]; // auto VLA: la longitud de este array se establece en for ( int i = 0 ; i < len ; i ++ ) { b [ i ] = 1 ; } // al final de esta función, b está dentro del marco de la pila y // desaparecerá cuando la función salga, por lo que no se requiere una llamada explícita a free(). }Véase también
Referencias
- ↑ "Ventajas de Alloca" . La biblioteca C de GNU .
- ↑ "En línea" . Usando la colección de compiladores GNU (GCC) .
- ↑ "Código fuente de Alloca.c [ libiberty/Alloca.c ] - Navegador de código" .
- ↑ – Manual del programador de Linux – Funciones de la biblioteca
- ↑ "¿Por qué no se considera una buena práctica el uso de alloca()?" . stackoverflow.com . Consultado el 5 de enero de 2016 .
- ↑ "_malloca" . Documentación de Microsoft CRT .
- ↑ "gnulib/malloca.h" . GitHub . Consultado el 24 de noviembre de 2019 .
- ↑ "glibc/include/alloca.h" . Espejos de Beren Minor. 23 de noviembre de 2019.
- ↑ "Definición ISO C 99" (PDF) . Consultado el 10 de abril de 2022 .
- ↑ "Declaración de matriz" . cppreference.com . Consultado el 12 de septiembre de 2025 .
- Gestión de la memoria