direcciones - ¿Por qué querrías asignar memoria en el montón en lugar de la pila?
stack y heap c# (9)
Posible duplicado:
¿Cuándo es mejor usar una Pila en lugar de una Pila y viceversa?
He leído algunas de las otras preguntas con respecto a la pila Heap vs, pero parecen enfocarse más en lo que hace la pila / montón en lugar de por qué las usarías.
Me parece que la asignación de stack casi siempre sería la preferida, ya que es más rápida (solo mover el puntero de la pila y buscar espacio libre en el montón), y no es necesario que libere memoria asignada manualmente cuando termine de usarla . La única razón que puedo ver para usar la asignación de montón es si desea crear un objeto en una función y luego usarlo fuera de ese alcance de funciones, ya que la memoria asignada de pila se asigna automáticamente después de regresar de la función.
¿Hay otras razones para usar la asignación de heap en lugar de la asignación de la pila que no conozco?
- Desea una asignación para vivir más allá de una invocación de función
- Desea conservar el espacio de pila (que generalmente está limitado a unos pocos MB)
- Está trabajando con memoria reubicable (Win16, bases de datos, etc.) o quiere recuperarse de fallas de asignación.
- Longitud variable cualquier cosa. Puedes fingir esto, pero tu código será realmente desagradable.
El grande es # 1. Tan pronto como entre en algún tipo de concurrencia o IPC # 1 estará en todas partes. Incluso la mayoría de las aplicaciones de un único subproceso no triviales son difíciles de diseñar sin alguna asignación de montón. Eso prácticamente simulaba un lenguaje funcional en C / C ++.
Además del control manual de la duración del objeto (que usted mencionó), las otras razones para usar el montón incluirían:
- Control en tiempo de ejecución sobre el tamaño del objeto (tanto su tamaño inicial como su tamaño "posterior", durante la ejecución del programa).
Por ejemplo, puede asignar una matriz de cierto tamaño, que solo se conoce en tiempo de ejecución.
Con la introducción de VLA (Variable Length Arrays) en C99, fue posible asignar matrices de tamaño de tiempo de ejecución fijo sin usar heap (esto es básicamente una implementación a nivel de lenguaje de la funcionalidad ''alloca''). Sin embargo, en otros casos, todavía necesitarías un montón incluso en C99.
- Control en tiempo de ejecución sobre el número total de objetos.
Por ejemplo, cuando construyes una estructura de árbol binario, no puedes asignar los nodos del árbol en la pila de antemano de manera significativa. Debes usar heap para asignarlos "a pedido".
- Consideraciones técnicas de bajo nivel, como espacio de pila limitado (otros ya mencionaron eso).
Cuando necesite un gran búfer de E / S, por ejemplo, incluso durante un breve período de tiempo (dentro de una sola función), tiene más sentido solicitarlo del montón en lugar de declarar un conjunto automático grande.
Entonces quiero hacer una cadena. Puedo hacerlo en el montón o en la pila. Probemos ambos:
char *heap = malloc(14);
if(heap == NULL)
{
// bad things happened!
}
strcat(heap, "Hello, world!");
Y para la pila:
char stack[] = "Hello, world!";
Así que ahora tengo estas dos cadenas en sus respectivos lugares. Más tarde, quiero hacerlos más largos:
char *tmp = realloc(heap, 20);
if(tmp == NULL)
{
// bad things happened!
}
heap = tmp;
memmove(heap + 13, heap + 7);
memcpy(heap + 7, "cruel ", 6);
Y para la pila:
// umm... What?
Este es solo un beneficio, y otros han mencionado otros beneficios, pero este es bastante bueno. Con el montón, al menos podemos tratar de hacer que nuestro espacio asignado sea más grande. Con la pila, estamos atrapados con lo que tenemos. Si queremos espacio para crecer, tenemos que declararlo todo por adelantado, y todos sabemos cómo apesta ver esto:
char username[MAX_BUF_SIZE];
Hay unas pocas razones:
- El principal es que con la asignación de montón, tiene el control más flexible sobre la vida del objeto (de
malloc
/calloc
afree
); - El espacio de pila suele ser un recurso más limitado que el espacio de pila, al menos en las configuraciones predeterminadas;
- Una falla para asignar espacio de montón se puede manejar con gracia, mientras que quedarse sin espacio de pila a menudo es irrecuperable.
Sin la duración flexible del objeto, las estructuras de datos útiles como árboles binarios y listas vinculadas serían prácticamente imposibles de escribir.
La pila y el montón comparten el mismo espacio de memoria "abierto" y finalmente tendrán que llegar al punto donde se encuentran, si usa todo el segmento de la memoria. Mantener el equilibrio entre el espacio que utiliza cada uno de ellos tendrá un costo amortizado más tarde para la asignación y la desasignación de la memoria un valor asintótico más pequeño.
La razón más obvia para usar el montón es cuando llamas a una función y necesitas que se devuelva algo de longitud desconocida. Algunas veces la persona que llama puede pasar un bloque de memoria y tamaño a la función, pero en otras ocasiones esto no es práctico, especialmente si el material devuelto es complejo (por ejemplo, una colección de objetos diferentes con punteros volando, etc.).
Las variables de pila (a menudo llamadas ''variables automáticas'') se usan mejor para las cosas que siempre quiere que sean iguales, y siempre son pequeñas.
int x;
char foo[32];
Son todas las asignaciones de pila, Estas también se arreglan en tiempo de compilación.
La mejor razón para la asignación del montón es que no siempre se puede saber cuánto espacio necesita. A menudo solo se sabe esto una vez que el programa se está ejecutando. Puede tener una idea de los límites, pero solo desea utilizar la cantidad exacta de espacio requerido.
Si tuviera que leer en un archivo que podría ser cualquier cosa desde 1k hasta 50mb, no haría esto: -
int readdata ( FILE * f ) {
char inputdata[50*1024*1025];
...
return x;
}
Eso trataría de asignar 50mb en la pila, lo que normalmente fallaría ya que la pila generalmente está limitada a 256k de todos modos.
Los límites de tamaño son un gran obstáculo en muchos casos. La pila generalmente se mide en megabytes bajos o incluso kilobytes (eso es para todo en la pila), mientras que todas las PC modernas te permiten unos pocos gigabytes de pila. Entonces, si va a utilizar una gran cantidad de datos, absolutamente necesita el montón.
solo para agregar puede usar alloca para asignar memoria en la pila, pero nuevamente la memoria en la pila es limitada y también el espacio existe solo durante la ejecución de la función solamente. eso no significa que todo debe ser asignado en el montón. como todas las decisiones de diseño, esto también es algo difícil, se debe usar una combinación "juiciosa" de ambos.