close

Pila de llamadas

Saltar a navegación Saltar a búsqueda

En informática , una pila de llamadas (traducido literalmente del inglés como "call stack") es un área de memoria de un programa, organizada en forma de pila , en la que se almacena información sobre las subrutinas activas en un momento dado ( las subrutinas activas son aquellas que han sido invocadas pero cuya ejecución no ha terminado). Se puede traducir como una pila de invocaciones de funciones (o llamadas de funciones ) o una pila de invocaciones de métodos (o llamadas de métodos ) dependiendo del tipo de subrutina involucrada.

Este tipo de pila también suele denominarse pila de ejecución, pila de control, pila de funciones o pila de tiempo de ejecución o, cuando no hay posibilidad de confusión, simplemente pila .

El conjunto de información específica de una subrutina dentro de una pila de llamadas se denomina marco .

Operación

Image
Ejemplo

La razón por la que necesita adoptar una pila de llamadas es para realizar un seguimiento de dónde debe devolver el control cada subrutina activa cuando finaliza la ejecución. Si, por ejemplo, una subrutina DrawSquare (dibujar un cuadrado) llama a la subrutina DrawLine (dibujar una línea) desde cuatro puntos diferentes, el código DrawLine debe poder saber a dónde regresar después de la ejecución. Esta tarea generalmente la realiza el código para cada llamada dentro de DrawSquare al insertar la dirección de instrucción después de una "dirección de retorno" particular dentro de la pila de llamadas.

Dado que la pila de llamadas está organizada como una pila, la función de llamada coloca la dirección de retorno en la parte superior de la pila y la subrutina llamada, cuando finaliza, toma la dirección de retorno de la pila y transfiere el control a esa dirección. Si una subrutina llamada llama a otra subrutina, colocará la dirección de retorno encima de la pila de llamadas y así sucesivamente, la información se apilará y eliminará según lo esperado por el programa . Si se utiliza todo el espacio disponible para la pila de llamadas, se produce un error llamado desbordamiento de pila . Agregar una subrutina a la pila de llamadas se denomina liquidación ; quitarlo se llama desenrollar.

Por lo general, solo hay una pila de llamadas asociada con un programa en ejecución (o más precisamente con cada tarea o subproceso de un proceso), sin embargo, se pueden crear pilas adicionales para manejar señales o para multitarea cooperativa . Dado que solo hay uno en este importante contexto, simplemente nos referimos a la pila (implícitamente "de la tarea").

En los lenguajes de programación de alto nivel , las especificaciones de la pila de llamadas están ocultas para el programador . Este último tiene acceso sólo a la lista de funciones y no a la memoria ocupada por la pila, ni a la estructura interna adoptada. Muchos lenguajes ensambladores , por otro lado, requieren que los programadores participen en la gestión de la pila. Los detalles de la pila en un lenguaje de programación también dependen del compilador, el sistema operativo y las instrucciones disponibles.

Propósito de la pila de llamadas

El propósito principal de la pila de llamadas es:

  • almacenar direcciones de retorno : cuando se llama a una subrutina, la dirección de la instrucción de retorno debe almacenarse en algún lugar. El uso de una pila para almacenar direcciones de retorno tiene grandes ventajas sobre las alternativas. Una de ellas es que cada tarea tiene su propia pila y, por lo tanto, las subrutinas pueden ser "reentrantes" y, por lo tanto, pueden estar activas simultáneamente para diferentes tareas que hacen cosas diferentes. Otra ventaja es que la recursividad se admite automáticamente. Cuando una función se llama a sí misma recursivamente, se debe registrar una dirección de retorno para cada activación de función para que pueda usarse para el retorno de cada activación de función. Esta capacidad es automática con una pila.

Una pila de llamadas puede tener propósitos adicionales, según el idioma, el sistema operativo y el entorno de la máquina. Entre estos:

  • almacenar datos locales : una subrutina necesita con frecuencia espacio de memoria para registrar los valores de las variables locales, variables utilizadas solo en la subrutina activa y que no deben contener valores después de regresar (a la función de llamada). A menudo es conveniente asignar espacio para este uso para simplemente pasar a la parte superior de la pila lo suficiente como para tener el espacio. Es muy rápido en comparación, por ejemplo, con la asignación de montones . Cada activación diferente de una subrutina tiene su propio espacio de pila separado para datos locales.
  • pasar parámetros : las subrutinas a menudo requieren que el código que las llama proporcione valores de parámetros, y no es raro que haya espacio para estos parámetros en la pila de llamadas. En general, si solo hay unos pocos parámetros pequeños, los registros del procesador se pueden usar para pasar valores, pero si hay más parámetros para administrar de esta manera, se requiere espacio en la memoria. La pila de llamadas funciona mejor como un lugar para estos parámetros, especialmente porque cada llamada de subrutina, que tendrá diferentes valores de parámetros, tendrá un espacio separado en la pila de llamadas para estos valores.
  • pila de evaluación : los operandos para operaciones aritméticas y lógicas a menudo se ingresan en el registro y se usan allí. Sin embargo, en algunas situaciones, los operandos se pueden apilar hasta una profundidad arbitraria, lo que significa que se debe usar algo más que el registro. La pila de estos operandos, similar a las computadoras de tipo RPN, se denomina pila de evaluación y puede ocupar espacio en la pila de llamadas.
  • puntero de instancia actual : algunos lenguajes orientados a objetos (como C ++ ) almacenan este puntero como un argumento para las funciones en la pila de llamadas cuando se invoca un método. Este puntero apunta a la instancia del objeto con el que está asociado el método invocado. Es una parte esencial del contexto de ejecución de los lenguajes orientados a objetos, ya que proporciona acceso a los datos que posee el objeto actual. Este puntero está vinculado a las capas utilizadas en la programación orientada a objetos en capas (tipos de estructuras de pila) de la pila de llamadas en tiempo de ejecución.
  • Entorno contenedor de subrutinas : algunos lenguajes de programación (como Pascal y Ada ) admiten subrutinas anidadas , lo que permite que una rutina interna acceda al contexto de su rutina contenedora, es decir, a parámetros y variables locales en el entorno de la rutina externa. Dichos lenguajes generalmente permiten que las rutinas realicen llamadas recursivas (la función se llama a sí misma), lo que da como resultado múltiples pilas de llamadas para llamadas de rutina a rutinas internas, cada una apuntando al mismo entorno que la rutina externa. Este tipo de marco de llamada también se conoce como pantalla .

Artículos relacionados