Asignación de memoria basada en pila - Stack-based memory allocation

Una pila típica, que almacena datos locales e información de llamadas para llamadas a procedimientos anidados (no necesariamente procedimientos anidados ). Esta pila crece hacia abajo desde su origen. El puntero de la pila apunta al dato superior actual de la pila. Una operación de inserción reduce el puntero y copia los datos en la pila; una operación emergente copia datos de la pila y luego incrementa el puntero. Cada procedimiento llamado en el programa almacena información de retorno de procedimiento (en amarillo) y datos locales (en otros colores) empujándolos a la pila.

Las pilas en las arquitecturas informáticas son regiones de memoria donde los datos se agregan o eliminan de una manera LIFO (último en entrar, primero en salir) .

En la mayoría de los sistemas informáticos modernos, cada subproceso tiene una región reservada de memoria denominada pila. Cuando se ejecuta una función, puede agregar algunos de sus datos de estado local a la parte superior de la pila; cuando la función sale, es responsable de eliminar esos datos de la pila. Como mínimo, la pila de un hilo se usa para almacenar la ubicación de una dirección de retorno proporcionada por la persona que llama para permitir que las declaraciones de retorno regresen a la ubicación correcta. La pila se usa a menudo para almacenar variables de longitud fija locales a las funciones activas actualmente. Los programadores pueden optar además por utilizar explícitamente la pila para almacenar datos locales de longitud variable. Si una región de memoria se encuentra en la pila del subproceso, se dice que esa memoria se ha asignado a la pila, es decir, la asignación de memoria basada en la pila .

Ventajas y desventajas

Debido a que los datos se agregan y eliminan de una manera de último en entrar, primero en salir, la asignación de memoria basada en pilas es muy simple y, por lo general, mucho más rápida que la asignación de memoria basada en montones (también conocida como asignación de memoria dinámica ) que normalmente se asigna a través de malloc. Otra característica es que la memoria en la pila se recupera de manera automática y muy eficiente cuando la función sale, lo que puede ser conveniente para el programador si los datos ya no son necesarios. (Lo mismo se aplica a longjmp si se movió a un punto antes de que allocaocurriera la llamada a ). Sin embargo, si los datos deben mantenerse de alguna forma, entonces deben copiarse de la pila al montón antes de que la función salga. Por lo tanto, la asignación basada en pila es adecuada para datos temporales o datos que ya no son necesarios después de que finaliza la función actual.

El tamaño de pila asignado a un hilo puede ser tan pequeño como unos pocos bytes en algunas CPU pequeñas. La asignación de más memoria en la pila de la disponible puede provocar un bloqueo debido al desbordamiento de la pila . Esta es también la razón por la que las funciones que se usan allocageneralmente no se pueden insertar: si una función de este tipo se inserta en un bucle, la persona que llama sufriría un crecimiento no anticipado en el uso de la pila, lo que haría mucho más probable un desbordamiento.

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 tanto los punteros de pila como los de marco deben administrarse (con marcos de pila de tamaño fijo, uno de estos es redundante). Esto suele ser mucho menos costoso que llamar mallocy de freetodos modos. En particular, si la función actual contiene llamadas a alloca y 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 sale frente a la necesidad del compilador de colocar variables locales de longitud variable en el misma ubicación en el marco de la pila. Este conflicto generalmente se resuelve creando una cadena separada de almacenamiento dinámico para cada llamada a alloca (consulte: https://code.woboq.org/gcc/libiberty/alloca.c.html ). La cadena registra la profundidad de la pila a la que se produce cada asignación, las llamadas posteriores para asignar en cualquier función recortan esta cadena hasta la profundidad de la pila actual para liberar eventualmente (pero no inmediatamente) cualquier almacenamiento en esta cadena. Una llamada a alloca con un argumento de cero también se puede usar para activar la liberación de memoria sin asignar más memoria. Como consecuencia de este conflicto entre alloca y el almacenamiento de variables locales, es posible que el uso de alloca no sea más eficiente que el uso de malloc.

Interfaz del sistema

Muchos sistemas similares a Unix, así como Microsoft Windows, implementan una función llamada allocapara asignar dinámicamente memoria de pila de una manera similar a la basada en montones malloc. Un compilador normalmente lo traduce a instrucciones en línea que manipulan el puntero de la pila, de forma similar a cómo se manejan las matrices de longitud variable . Aunque no es necesario liberar explícitamente la memoria, existe el riesgo de un comportamiento indefinido debido al desbordamiento de la pila. La función estaba presente en los sistemas Unix desde 32 / V (1978), pero no es parte del estándar C ni de ningún estándar POSIX .

Existe una versión más segura de allocacalled _malloca, que informa de errores, en Microsoft Windows. Requiere el uso de _freea. gnulib proporciona una interfaz equivalente, aunque en lugar de lanzar una excepción SEH en caso de desbordamiento, delega malloccuando se detecta un tamaño excesivo. Se puede emular una característica similar usando contabilidad manual y verificación de tamaño, como en los usos de alloca_accounten glibc.

Algunas familias de procesadores, como x86 , tienen instrucciones especiales para manipular la pila del subproceso que se está ejecutando actualmente. Otras familias de procesadores, incluidos PowerPC y MIPS , no tienen soporte explícito de pila, sino que dependen de la convención y delegan la gestión de pila a la interfaz binaria de aplicación (ABI) del sistema operativo .

Ver también

Referencias