¿Qué y dónde están la pila y el montón?

Los libros en lenguajes de programación explican que los tipos de valor se crean en la pila , y los tipos de referencia se crean en el montón , sin explicar cuáles son estas dos cosas. No he leído una explicación clara para esto. Entiendo lo que es una pila. Pero

  • ¿Dónde y qué son (físicamente en la memoria de la computadora real)?
  • ¿En qué medida están controlados por el sistema operativo o el idioma?
  • ¿Cuál es su volumen?
  • ¿Qué determina el tamaño de cada uno de ellos?
  • ¿Qué hace más rápido?
7380
17 сент. set de mattshane 17 sep . 2008-09-17 07:18 '08 a las 7:18 am 2008-09-17 07:18
@ 25 respuestas

Una pila es una memoria reservada como espacio de memoria virtual para un subproceso de ejecución. Cuando se llama a una función, el bloque se reserva en la parte superior de la pila para las variables locales y algunas credenciales. Cuando esta función regresa, el bloque deja de utilizarse y puede usarse la próxima vez que se llame a la función. La pila siempre se reserva en el orden de LIFO (el último en el primer orden); el bloque reservado más reciente es siempre el siguiente bloque que se lanzará. Esto facilita el seguimiento de la pila; liberar un bloque de la pila no es más que un simple ajuste de puntero.

Un montón es una memoria asignada para la asignación dinámica. A diferencia de la pila, no hay una plantilla forzada para asignar y liberar bloques de un montón; Puede seleccionar un bloque en cualquier momento y liberarlo en cualquier momento. Esto hace que sea muy difícil rastrear qué partes del montón se distribuyen o liberan en un momento dado; Hay muchos distribuidores cum personalizados para ajustar el rendimiento del montón para diferentes patrones de uso.

Cada subproceso recibe una pila, mientras que para una aplicación solo se usa un montón (aunque no es raro tener varios montones para diferentes tipos de ubicación).

Para responder a sus preguntas directamente:

¿En qué medida están controlados por el sistema operativo o el idioma?

El sistema operativo asigna una pila para cada subproceso de nivel de sistema al crear un subproceso. Normalmente, el entorno de ejecución de lenguaje llama al sistema operativo para asignar un montón para una aplicación.

¿Cuál es su volumen?

La pila está unida al hilo, de modo que cuando el hilo sale de la pila, se corrige. Por lo general, se asigna un montón cuando la aplicación se inicia en el tiempo de ejecución y se devuelve después de que la aplicación (proceso técnico) sale.

¿Qué determina el tamaño de cada uno de ellos?

El tamaño de pila se establece al crear un hilo. El tamaño del montón se establece cuando se inicia la aplicación, pero puede aumentar según sea necesario (el asignador solicita más memoria del sistema operativo).

¿Qué hace más rápido?

La pila es más rápida porque el patrón de acceso hace que sea trivial para asignar y liberar memoria de ella (el puntero / entero simplemente crece o se reduce), y el montón tiene estados financieros mucho más complicados relacionados con la asignación o la liberación. Además, cada byte en la pila a menudo se reutiliza, lo que significa que tiende a mostrarse en la memoria caché del procesador, lo que lo hace muy rápido. Otro impacto del rendimiento del montón es que el montón, que es principalmente un recurso global, normalmente debería ser multihebra, es decir, Cada distribución y versión debe estar, como regla general, sincronizada con "todas" las demás llamadas de montón en el programa.

Demostración clara: 2019

5436
17 сент. La respuesta está dada por Jeff Hill 17 sep. 2008-09-17 07:52 '08 a las 7:52 am del 2008-09-17 07:52

Apilar

  • Guardado en la memoria RAM de la computadora, como un montón.
  • Las variables creadas en la pila quedan fuera del alcance y se liberan automáticamente.
  • Mucho más rápido para asignar en comparación con las variables en el montón.
  • Implementado con la estructura de datos de la pila real.
  • Guarda datos locales, devuelve direcciones usadas para pasar parámetros.
  • Puede tener un desbordamiento de pila cuando se usa demasiado de la pila (en su mayoría de recursión infinita o demasiado profunda, distribuciones muy grandes).
  • Los datos creados en la pila se pueden utilizar sin punteros.
  • Usaría la pila si supiera exactamente cuántos datos necesita asignar antes de compilar, y no es demasiado grande.
  • Por lo general, el tamaño máximo ya está determinado cuando se inicia el programa.

Montón

border=0
  • Almacenado en la memoria de la computadora de la misma manera que la pila.
  • En C ++, las variables en el montón deben destruirse manualmente y nunca quedar fuera de alcance. Los datos se liberan con delete , delete[] o free .
  • Es más lento para asignar en comparación con las variables en la pila.
  • Se utiliza a pedido para asignar un bloque de datos para uso del programa.
  • Puede tener fragmentación cuando hay muchas asignaciones y exenciones.
  • En C ++ o C, los datos creados en el montón se indicarán mediante punteros y se asignarán a new o malloc respectivamente.
  • Puede fallar en la distribución si se requiere demasiado búfer.
  • Usted usaría un grupo si no sabe exactamente cuántos datos necesita en tiempo de ejecución o si necesita asignar una gran cantidad de datos.
  • Responsable de la pérdida de memoria.

Ejemplo:

2164
17 сент. La respuesta la da Brian R. Bondy 17 sep. 2008-09-17 07:20 '08 a las 7:20 2008-09-17 07:20

El punto más importante es que el montón y la pila son términos generales para los métodos de asignación de memoria. Se pueden implementar de diferentes maneras, y estos términos son aplicables a conceptos básicos.

  • En la pila de elementos, los elementos se colocan uno encima del otro en el orden en que se colocaron allí, y solo se puede quitar la parte superior (sin inclinar todo el elemento).

    2019

1294
19 марта '09 в 17:38 2009-03-19 17:38 la respuesta la da thomasrutter el 19 de marzo de 2009 a las 17:38 2009-03-19 17:38

(Cambié esta respuesta de otra pregunta que fue más o menos engañada por ella).

La respuesta a su pregunta es específica de la implementación y puede variar entre compiladores y arquitecturas de procesador. Sin embargo, esta es una explicación simplificada.

  • Tanto la pila como el montón son áreas de memoria asignadas desde el sistema operativo base (a menudo memoria virtual, que se asigna a la memoria física a pedido).
  • En un entorno de subprocesos múltiples, cada subproceso tendrá su propia pila totalmente independiente, pero dividirá el montón. El acceso paralelo se debe controlar en el montón y no es posible en la pila.

Una pila

  • El montón contiene una lista enlazada de bloques usados ​​y libres. Las nuevas asignaciones de pilas ( new o malloc ) se satisfacen creando un bloque adecuado a partir de uno de los bloques libres. Esto requiere actualizar la lista de bloques en el montón. Esta metainformación sobre bloques en un montón también se almacena en un montón, a menudo en un área pequeña justo antes de cada bloque.
  • A medida que crece el montón, a menudo se asignan nuevos bloques de direcciones inferiores a direcciones superiores. Por lo tanto, puede pensar en un montón como una pila de bloques de memoria que crecen en tamaño a medida que se asigna la memoria. Si el montón es demasiado pequeño para distribuirlo, el tamaño a menudo se puede aumentar al adquirir más memoria del sistema operativo subyacente.
  • Asignar y liberar muchos bloques pequeños puede dejar una pila en un estado en el que hay muchos pequeños bloques libres intercalados entre los bloques usados. La solicitud de asignación de un bloque grande puede fallar, porque ninguno de los bloques libres es lo suficientemente grande como para satisfacer la solicitud de distribución, incluso si el tamaño combinado de los bloques libres puede ser lo suficientemente grande. Esto se llama fragmentación del montón.
  • Cuando se libera un bloque usado adyacente a un bloque libre, se puede combinar un nuevo bloque libre con un bloque libre adyacente para crear un bloque libre más grande que reduzca efectivamente la fragmentación del montón.

2019

681
31 июля '09 в 18:54 2009-07-31 18:54 La respuesta la da Martin Liversage el 31 de julio de 2009 a las 18:54 2009-07-31 18:54

En el siguiente código C #

var _tmr = window._tmr || (window._tmr = []);_tmr.push({id: "2334768", type: "pageView", start: (new Date()).getTime()});(function (d, w, id) {  if (d.getElementById(id)) return;  var ts = d.createElement("script"); ts.type = "text/javascript"; ts.async = true; ts.id = id;  ts.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//top-fwz1.mail.ru/js/code.js";  var f = function () {var s = d.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ts, s);};  if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); }})(document, window, "topmailru-code");