Pregunta

Estaba buscando una regla de oro para asignar objetos en la pila o el montón en C ++. He encontrado muchas discusiones aquí sobre SO. Mucha gente dijo que se trata de la vida útil de un objeto. Si necesita más tiempo de vida que el alcance de la función, póngalo en el montón. Eso tiene mucho sentido.

Pero lo que me confundió es que, según mucha gente, asignar objetos para apilar si son pequeños. Si los objetos son grandes, póngalo en el montón. ¿Pero ninguno de ellos dijo cómo identificar un objeto es grande o no?

Tengo las siguientes preguntas,

  1. ¿Cómo identificar un objeto es grande o no?
  2. ¿Cuál será el tamaño máximo de la pila? ¿Cada sistema operativo tendrá un tamaño de pila diferente?
  3. Tengo una clase de contenedor que envuelve vector<string>. Tendrá alrededor de 100 artículos. ¿Se desbordará una pila si asigno esta clase a una pila? Intenté esto, pero funcionó perfectamente. No estoy seguro de que estoy haciendo algo mal.
¿Fue útil?

Solución

Bueno, en primer lugar, los vectores (y todas las clases de contenedor STL) siempre se asignan desde el montón para que no tenga que preocuparse por eso. Para cualquier contenedor con un tamaño variable es prácticamente imposible usar la pila.

Si piensa en cómo funciona la asignación de pila (en tiempo de compilación, básicamente incrementando un puntero para cada objeto), entonces debería quedar claro que la memoria vectorial proviene del montón.

std::vector<int> myInts;
std::string myString;
SomeOther Class;

// this memory must come from the heap, there's no way it
// can now be allocated on the stack since there are other
// objects and these parameters could be variable
myString = "Some String";
myInts.reserve(256);

A menos que esté en una función recursiva, puede colocar varios kilobytes de datos en la pila sin mucha preocupación. Los tamaños de pila están controlados por el programa (no por el sistema operativo) y el valor predeterminado tiende a oscilar entre 32kb y 1mb. La mayoría del software de escritorio viene en el rango de 1mb.

Los objetos individuales casi nunca son una preocupación. En general, serán lo suficientemente pequeños para la pila o se asignarán internamente desde el montón.

Si los objetos son locales para una función, colóquelos en la pila. Si no, póngalos en el montón.

Use el montón para grandes memorias intermedias que asigne para cargar / ordenar / manipular datos.

Otros consejos

Según MSDN valores predeterminados de pila a 1mb. (Esto es para Msdev obviamente).

Como puede ver en el artículo, puede modificar el tamaño de la pila en tiempo de compilación con el indicador / F.

Creo que su primera directriz para el uso de pila vs montón es bastante precisa, con la calificación de que si su variable de alcance temporal es más grande que un mb, péguela en el montón (y probablemente pregunte por qué está asignando tanta memoria para un corto período de tiempo en primer lugar).

La única forma en que puede asignar objetos grandes en la pila es involucrar una matriz de estilo antiguo en algún momento. Por ejemplo:

void f() {
   char a[1000000];    // big object on the stack
}

struct A {
   char c[1000000];
};

void g() {
   A a;      // another big object on the stack
}

Si no usa matrices (y no debería hacerlo), la mayoría de las cosas se asignarán en el montón:

void h() {
   std::string s( 100000 );
}

lo anterior asigna unos pocos bytes en la pila para punteros, información de tamaño, etc. y luego asigna el almacenamiento real en el montón.

¡Así que deja de preocuparte! ¡Probablemente estás haciendo las cosas bien!

  

¿Cómo identificar un objeto es grande o no?

Depende de su compilador / plataforma combinada. No hay un límite verdadero. Los compiladores a menudo le permiten ajustar esto.

  

¿Cuál será el tamaño máximo de la pila? ¿Cada sistema operativo tendrá un tamaño de pila diferente?

Depende principalmente de lo anterior. Lo único que tiene menos control de sintonización.

  

Tengo una clase de contenedor que ajusta el vector. Tendrá alrededor de 100 artículos. ¿Se desbordará una pila si asigno esta clase a una pila? Intenté esto, pero funcionó perfectamente. No estoy seguro de que estoy haciendo algo mal.

Funcionará siempre que el requisito de memoria total de este contenedor y otros objetos en ese bloque no exceda el tamaño del marco de la pila. Lo que a su vez depende de la cadena media sie.

Una buena idea es pasar por un depurador y ver las direcciones de la pila; eso te dará un comienzo del ancho hasta cierto punto. Y la documentación.

1. ¿Cómo identificar un objeto es grande o no?

Use " sizeof "

class c {
  std::vector<std::string> s;
};

int size = sizeof (c);

En mi máquina " size " es de 16 bytes.

2. ¿Cuál será el tamaño máximo de la pila? ¿Cada sistema operativo tendrá un tamaño de pila diferente?

No se puede decir, pero definitivamente no es un buen lugar para asignar grandes cantidades de datos.

3. Tengo una clase de contenedor que envuelve el vector. Tendrá alrededor de 100 artículos. ¿Se desbordará una pila si asigno esta clase a una pila? Intenté esto, pero funcionó perfectamente. No estoy seguro de que estoy haciendo algo mal.

No. std :: vector asigna los 100 elementos en el montón.

Un punto más que mencionaré es que debido a que vector<> debe poder cambiar su tamaño, si crece lo suficiente (ver más abajo) debe usar el montón para almacenar sus objetos contenidos, incluso si el <=> en sí mismo se declara como una variable de pila.

[EDIT] Como Motti señala en un comentario, es posible que <=> reserve una pequeña cantidad de espacio dentro de su objeto asignado por pila como una optimización para pequeños vectores. En ese caso, trabajar con vectores lo suficientemente pequeños como para caber dentro de este espacio no requerirá ninguna asignación de montón. (Este espacio preasignado debe ser bastante pequeño para evitar desperdiciar espacio cuando se trabaja con vectores más pequeños). Independientemente, si el vector crece lo suficientemente grande, requerirá (re) asignación en el montón.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top