2009-10-11 9 views
22

Duplicar posible:
When is it best to use a Stack instead of a Heap and vice versa?¿Por qué querrías asignar memoria en el montón en lugar de la pila?

He leído algunas de las otras preguntas relacionadas con el montón vs pila, pero parecen centrarse más en lo que la pila/pila hacer en lugar de por qué los usarías

Me parece que la asignación de la pila casi siempre sería la preferida, ya que es más rápida (solo mueve el puntero de la pila que buscar espacio libre en el montón), y no tienes que liberar manualmente la memoria asignada cuando " vuelto a usarlo. 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 montón en lugar de la asignación de la pila que no conozco?

+1

Duplicado: http://stackoverflow.com/questions/102009/when-is-it-best-to-use-a-stack-instead-of-a-heap-and-vice-versa – Naveen

+6

@Naveen: Sorta - la otra es una pregunta C++ donde esta es C, por lo que algunas de las respuestas discuten 'eliminar' y 'nuevo' que no son aplicables a C. –

Respuesta

36

Hay algunas razones:

  • La principal es que con la asignación del montón, usted tiene el control más flexible sobre la vida del objeto (de malloc/calloc a free);
  • 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 pila se puede manejar correctamente, 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.

4

La razón más obvia para utilizar el montón es cuando llama a una función y necesita devolver algo de longitud desconocida. A veces, la persona que llama puede pasar un bloque de memoria y tamaño a la función, pero otras veces esto no es práctico, especialmente si el material devuelto es complejo (por ejemplo, una colección de objetos diferentes con punteros volando, etc.).

19
  1. ¿Quieres una asignación de vivir más allá de una invocación de la función
  2. desea ahorrar espacio en la pila (que por lo general se limita a unos cuantos MB)
  3. Estás trabajando con la re-localizables memoria (Win16, bases de datos, etc.), o desea recuperarse de fallas de asignación.
  4. 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++.

8

Así que quiero hacer una cadena. Puedo hacerlo en el montón o en la pila.Vamos a tratar tanto:

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 hacerlas más largas:

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? 

esto es sólo uno de los beneficios, y otros han mencionado otros beneficios, pero este es un lugar agradable. 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 declarar todo por adelantado, y todos sabemos lo que apesta a ver esto:

char username[MAX_BUF_SIZE]; 
3

límites de tamaño son un gran motivo de ruptura 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 le permiten unos pocos gigabytes de pila. Entonces, si va a utilizar una gran cantidad de datos, absolutamente necesita el montón.

0

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 deba asignarse en el montón. como todo design decisions esto también es algo difícil, se debe usar una combinación "juiciosa" de ambos.

+0

Una vez más debo hacer que la 'función 'x()' no sea una "función estándar" comentario. 'alloca()' se encuentra en muchas plataformas de una forma u otra, pero no forma parte de ningún estándar. –

+0

Chris: Esto es absolutamente cierto, sin embargo, en el contexto de una discusión más amplia de la asignación de pila versus pila, la existencia de 'alloca()' en algunos lugares es útil a considerar. Particularmente porque muestra claramente que la limitación en el cálculo del tiempo de ejecución del tamaño de la asignación es una restricción impuesta por C, no algo inherente a la idea de la asignación basada en la pila. – caf

0

Además de control manual de la vida del objeto (que usted ha mencionado), los otros motivos para utilizar el montón incluirían:

  • de control en tiempo de ejecución sobre el tamaño del objeto (tanto en tamaño inicial y es "más adelante" tamaño, 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 (matrices de longitud variable) 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 de nivel de idioma 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 construye una estructura de árbol binario, no puede asignar de manera significativa los nodos del árbol en la pila de antemano. Debes usar heap para asignarlos "a pedido".

  • consideraciones técnicas de bajo nivel, como espacio de pila limitado (otros ya mencionaron que).

Cuando necesite un gran búfer de E/S, 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 una matriz automática grande.

0

Las variables de pila (a menudo llamadas 'variables automáticas') se utilizan 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 se puede saber siempre 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 de 1k a 50mb, no podría hacer esto: -

int readdata (FILE * f) { 
    char inputdata[50*1024*1025]; 
    ... 
    return x; 
} 

que trataría de asignar 50 MB en la pila, lo que suele fallar como la pila generalmente está limitada a 256k de todos modos.

0

La pila y el montón comparten el mismo espacio de memoria "abierto" y 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.

Cuestiones relacionadas