Asignación de memoria: astackmiento frente a montón?

Me estoy confundiendo con los conceptos básicos de asignación de memoria entre Stack vs Heap . Según la definición estándar (cosas que todo el mundo dice), todos los tipos de valores se asignarán a una stack y los tipos de referencia irán al montón .

Ahora considere el siguiente ejemplo:

class MyClass { int myInt = 0; string myString = "Something"; } class Program { static void Main(string[] args) { MyClass m = new MyClass(); } } 

Ahora, ¿cómo sucederá la asignación de memoria en c #? ¿El objeto de MyClass (es decir, m ) se asignará por completo al Heap? Es decir, int myInt y string myString ambos irán al montón?

O bien, el objeto se dividirá en dos partes y se asignará a las dos ubicaciones de memoria, es decir, Pila y Heap.

m se asigna en el montón, y eso incluye myInt . Las situaciones donde los tipos primitivos (y las estructuras) se asignan en la stack se realizan durante la invocación del método, que asigna espacio para las variables locales en la stack (porque es más rápido). Por ejemplo:

 class MyClass { int myInt = 0; string myString = "Something"; void Foo(int x, int y) { int rv = x + y + myInt; myInt = 2^rv; } } 

rv , x , y estarán todos en la stack. myInt está en algún lugar en el montón (y debe tener acceso a través de this puntero).

Debería considerar la cuestión de dónde se asignan los objetos como detalle de implementación. No le importa exactamente dónde se almacenan los bits de un objeto. Puede importar si un objeto es un tipo de referencia o un tipo de valor, pero no tiene que preocuparse de dónde se almacenará hasta que comience a tener que optimizar el comportamiento de recolección de elementos no utilizados.

Si bien los tipos de referencia siempre se asignan en el montón en las implementaciones actuales, los tipos de valores se pueden asignar en la stack, pero no necesariamente. Un tipo de valor solo se asigna en la stack cuando es una variable local o temporal sin escape que no está contenida dentro de un tipo de referencia y no está asignada en un registro.

  • Si un tipo de valor es parte de una clase (como en su ejemplo), terminará en el montón.
  • Si está en caja, terminará en el montón.
  • Si está en una matriz, terminará en el montón.
  • Si es una variable estática, terminará en el montón.
  • Si es capturado por un cierre, terminará en el montón.
  • Si se usa en un iterador o en un bloque asincrónico, terminará en el montón.
  • Si es creado por un código inseguro o no administrado, podría asignarse en cualquier tipo de estructura de datos (no necesariamente una stack o un montón).

¿Hay algo que extrañé?

Por supuesto, sería negligente si no tuviera un enlace a las publicaciones de Eric Lippert sobre el tema:

  • La stack es un detalle de implementación, primera parte
  • La stack es un detalle de implementación, segunda parte
  • Y tal vez el mejor: La verdad sobre los tipos de valor

“Todos los tipos de VALOR se asignarán a Stack” es muy, muy incorrecto; las variables struct pueden vivir en la stack, como variables de método. Sin embargo, los campos de un tipo viven con ese tipo . Si el tipo que declara un campo es una clase, los valores están en el montón como parte de ese objeto. Si el tipo que declara un campo es una estructura, los campos son parte de esa estructura dondequiera que esa estructura viva.

Incluso las variables de método pueden estar en el montón, si se capturan (método lambda / anon) o como parte de (por ejemplo) un bloque iterador.

medidas simples

El tipo de valor se puede controlar en LA PILA, es el detalle de la implementación que se puede asignar a la estructura de datos futurista.

entonces, es mejor entender cómo funciona el valor y el tipo de referencia, el tipo de valor se copiará por valor, lo que significa que cuando pasa un tipo de valor como un param a una FUNCIÓN que será copiado por naturaleza significa que tendrá una copia total nueva .

Los tipos de referencia se pasan por referencia (aunque no se considera que la referencia almacenará una dirección nuevamente en algunas versiones futuras, puede almacenarse en algunas otras estructuras de datos).

entonces en tu caso

myInt es un int que está encapsulado en una clase que, por supuesto, tiene un tipo de referencia, por lo que estará vinculado a la instancia de la clase que se almacenará en ‘THE HEAP’.

Yo sugeriría, usted puede comenzar a leer blogs escritos por ERIC LIPPERTS.

Blog de Eric

Cada vez que se crea un objeto, entra en el área de memoria conocida como montón. Las variables primitivas como int y double se asignan en la stack, si son variables de método local y en el montón si son variables miembro. En los métodos, las variables locales se envían a la stack cuando se invoca un método y el puntero de la stack se reduce cuando se completa una llamada al método. En una aplicación multiproceso, cada subproceso tendrá su propia stack pero compartirá el mismo montón. Es por esto que se debe tener cuidado en su código para evitar cualquier problema de acceso concurrente en el espacio de almacenamiento dynamic. La stack es segura para los hilos (cada hilo tendrá su propia stack) pero el montón no es seguro para hilos a menos que esté protegido con sincronización a través de tu código.

Este enlace también es útil http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/

Astackr

La stack es un bloque de memoria para almacenar local variables y parameters local variables . La stack crece y se contrae de forma lógica a medida que se ingresa y sale una función.

Considera el siguiente método:

 public static int Factorial (int x) { if (x == 0) { return 1; } return x * Factorial (x - 1); } 

Este método es recursivo, lo que significa que se llama a sí mismo. Cada vez que se ingresa el método, se asigna un nuevo int en la stack , y cada vez que el método sale, el int se desasigna .


Montón

  • El montón es un bloque de memoria en el que residen objects (es decir, reference-type instances ). Cada vez que se crea un objeto nuevo, se asigna en el montón y se devuelve una referencia a ese objeto. Durante la ejecución de un progtwig, el montón comienza a llenarse a medida que se crean nuevos objetos. El tiempo de ejecución tiene un recolector de basura que periódicamente desasigna objetos del montón, por lo que su progtwig no se queda sin Out Of Memory . Un objeto es elegible para la desasignación tan pronto como no esté referenciado por nada que esté alive .
  • El montón también almacena static fields . A diferencia de los objetos asignados en el montón (que puede ser recolectado como basura), these live until the application domain is torn down .

Considera el siguiente método:

 using System; using System.Text; class Test { public static void Main() { StringBuilder ref1 = new StringBuilder ("object1"); Console.WriteLine (ref1); // The StringBuilder referenced by ref1 is now eligible for GC. StringBuilder ref2 = new StringBuilder ("object2"); StringBuilder ref3 = ref2; // The StringBuilder referenced by ref2 is NOT yet eligible for GC. Console.WriteLine (ref3); // object2 } } 

En el ejemplo anterior, comenzamos creando un objeto StringBuilder al que hace referencia la variable ref1, y luego escribimos su contenido. Ese objeto StringBuilder es inmediatamente elegible para la recolección de basura, porque nada la usa posteriormente. Luego, creamos otro StringBuilder al que hace referencia la variable ref2 y copiamos esa referencia a ref3. Aunque ref2 no ​​se utiliza después de ese punto, ref3 mantiene vivo el mismo objeto StringBuilder, asegurándose de que no sea elegible para la recostackción hasta que hayamos terminado de usar ref3.

Las instancias de tipo valor (y las referencias de objeto) se encuentran donde se haya declarado la variable. Si la instancia se declaró como un campo dentro de un tipo de clase, o como un elemento de matriz, esa instancia vive en el montón.

m es una referencia a un objeto de MyClass así que m se almacena en la stack de hilo principal pero el objeto de MyClass almacena en el montón. Por lo tanto, myInt y MyString almacenan en el montón. Tenga en cuenta que m es solo una referencia (una dirección a la memoria) y está en la stack principal. cuando m desasignado, entonces GC borra el objeto MyClass del montón Para más detalles, lea las cuatro partes de este artículo https://www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net- parte-i /