Saltar al contenido

¿Cómo se produce un “desbordamiento de pila” y cómo se evita?

Agradecemos tu ayuda para extender nuestros escritos con relación a las ciencias de la computación.

Solución:

Apilar

Una pila, en este contexto, es el último en entrar, el primero en salir del búfer que coloca los datos mientras se ejecuta el programa. Último en entrar, primero en salir (LIFO) significa que lo último que pone es siempre lo primero que saca: si empuja 2 elementos en la pila, ‘A’ y luego ‘B’, entonces lo primero que saca fuera de la pila será ‘B’, y lo siguiente es ‘A’.

Cuando llama a una función en su código, la siguiente instrucción después de la llamada a la función se almacena en la pila, y cualquier espacio de almacenamiento que pueda ser sobrescrito por la llamada a la función. La función a la que llame podría usar más pila para sus propias variables locales. Cuando termina, libera el espacio de la pila de variables locales que usó y luego regresa a la función anterior.

Desbordamiento de pila

Un desbordamiento de pila es cuando ha usado más memoria para la pila de la que se suponía que usaría su programa. En los sistemas integrados, es posible que solo tenga 256 bytes para la pila, y si cada función ocupa 32 bytes, solo puede tener llamadas de función 8 de profundidad: la función 1 llama a la función 2 quién llama a la función 3 quién llama a la función 4 … quién llama función 8 que llama a la función 9, pero la función 9 sobrescribe la memoria fuera de la pila. Esto podría sobrescribir la memoria, el código, etc.

Muchos programadores cometen este error llamando a la función A que luego llama a la función B, que luego llama a la función C, que luego llama a la función A. Podría funcionar la mayor parte del tiempo, pero solo una vez la entrada incorrecta hará que entre en ese círculo para siempre. hasta que la computadora reconozca que la pila está sobreexplotada.

Las funciones recursivas también son una causa de esto, pero si está escribiendo recursivamente (es decir, su función se llama a sí misma), entonces debe ser consciente de esto y usar static/variables globales para evitar la recursividad infinita.

En general, el sistema operativo y el lenguaje de programación que está utilizando administran la pila y está fuera de sus manos. Debe mirar su gráfico de llamadas (una estructura de árbol que muestra desde su principal a qué llama cada función) para ver qué tan profundas son sus llamadas de función y detectar ciclos y recurrencias que no están previstas. Los ciclos intencionales y la recursividad deben verificarse artificialmente para detectar errores si se llaman entre sí demasiadas veces.

Más allá de las buenas prácticas de programación, static y pruebas dinámicas, no hay mucho que pueda hacer en estos sistemas de alto nivel.

Sistemas embebidos

En el mundo integrado, especialmente en el código de alta confiabilidad (automóvil, aeronáutica, espacial), realiza revisiones y comprobaciones exhaustivas del código, pero también hace lo siguiente:

  • No permitir la recursividad y los ciclos: impuesto por la política y las pruebas
  • Mantenga el código y la pila separados (código en flash, pila en RAM y nunca se encontrarán los dos)
  • Coloque bandas de protección alrededor de la pila: un área vacía de la memoria que llena con un número mágico (generalmente una instrucción de interrupción de software, pero aquí hay muchas opciones), y cientos o miles de veces por segundo mira las bandas de protección para asegurarse no se han sobrescrito.
  • Usar protección de memoria (es decir, no ejecutar en la pila, no leer ni escribir fuera de la pila)
  • Las interrupciones no llaman a funciones secundarias: configuran indicadores, copian datos y dejan que la aplicación se encargue de procesarlos (de lo contrario, es posible que obtenga 8 en el árbol de llamadas de función, tenga una interrupción y luego salga otras funciones dentro del interrumpir, provocando la explosión). Tiene varios árboles de llamadas: uno para los procesos principales y otro para cada interrupción. Si tus interrupciones pueden interrumpirse entre sí… bueno, hay dragones…

Lenguajes y sistemas de alto nivel

Pero en lenguajes de alto nivel se ejecutan en sistemas operativos:

  • Reduzca su almacenamiento de variables locales (las variables locales se almacenan en la pila, aunque los compiladores son bastante inteligentes al respecto y, a veces, pondrán grandes locales en el montón si su árbol de llamadas es superficial)
  • Evitar o limitar estrictamente la recursividad
  • No divida sus programas demasiado en funciones cada vez más pequeñas, incluso sin contar las variables locales, cada llamada de función consume hasta 64 bytes en la pila (procesador de 32 bits, ahorrando la mitad de los registros de CPU, banderas, etc.)
  • Mantenga su árbol de llamadas poco profundo (similar a la declaración anterior)

servidores web

Depende de la ‘caja de arena’ que tenga si puede controlar o incluso ver la pila. Es muy probable que pueda tratar los servidores web como lo haría con cualquier otro lenguaje y sistema operativo de alto nivel: está en gran medida fuera de sus manos, pero verifique el idioma y la pila del servidor que está utilizando. Eso es posible volar la pila en su servidor SQL, por ejemplo.

-Adán

Un desbordamiento de pila en código real ocurre muy raramente. La mayoría de las situaciones en las que ocurre son recursiones en las que se ha olvidado la terminación. Sin embargo, podría ocurrir raramente en estructuras altamente anidadas, por ejemplo, documentos XML particularmente grandes. La única ayuda real aquí es refactorizar el código para usar un objeto de pila explícito en lugar de la pila de llamadas.

La mayoría de la gente le dirá que se produce un desbordamiento de pila con la recursividad sin una ruta de salida, mientras que la mayoría truesi trabaja con estructuras de datos lo suficientemente grandes, incluso una ruta de salida de recursividad adecuada no lo ayudará.

Algunas opciones en este caso:

  • Búsqueda en amplitud
  • Recurrencia de cola, excelente publicación de blog específica de .Net (lo siento, .Net de 32 bits)

Te mostramos las reseñas y valoraciones de los usuarios

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *