net diferencia and c# .net stack heap

c# - diferencia - Asignación de memoria: apilamiento frente a montón?



heap memory java (8)

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 pila 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.


Apilar

La stack es un bloque de memoria para almacenar local variables y parameters local variables . La pila 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 pila , 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 programa, 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 programa 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 recopilació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.


"Todos los tipos de VALOR se asignarán a Stack" es muy, muy incorrecto; las variables struct pueden vivir en la pila, 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.


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 pila, 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 pila cuando se invoca un método y el puntero de la pila se reduce cuando se completa una llamada al método. En una aplicación multiproceso, cada subproceso tendrá su propia pila 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 dinámico. La pila es segura para los hilos (cada hilo tendrá su propia pila) 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/


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 pila, pero no necesariamente. Un tipo de valor solo se asigna en la pila 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 pila 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:



m es una referencia a un objeto de MyClass así que m se almacena en la pila 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 pila 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-part-i/


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


m se asigna en el montón, y eso incluye myInt . Las situaciones donde los tipos primitivos (y las estructuras) se asignan en la pila se realizan durante la invocación del método, que asigna espacio para las variables locales en la pila (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 pila. myInt está en algún lugar en el montón (y debe tener acceso a través de this puntero).