2009-12-19 16 views

Respuesta

28

Eric Lippert habla de esto here; en primer lugar, es incorrecto que "los tipos de valores estén almacenados en la pila".Ellos veces son, pero no como:

  • campos de una clase
  • las variables capturadas
  • variables en un bloque de iterador

Cuando pueden ser almacenados en la pila se es una forma conveniente de modelar su tiempo de vida, pero no es requerido para almacenarlos en la pila. Puede escribir un compilador + CLI que no tenga tenga una pila, por ejemplo.

+4

También vea http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx –

+0

El artículo en el enlace de arriba es brillante, ¿por qué no tiene más votos ascendentes? –

0

Operación de pila o operación Heap, ambas serán las mismas que está accediendo a una dirección de memoria que están en dos ubicaciones diferentes.

Los tipos de valores son pequeños, int, byte, etc., son de pequeño tamaño y se mencionan con mucha frecuencia en términos de cálculos matemáticos. Dado que son de un tamaño muy pequeño, de 4 a 16 bytes como máximo, (no debe usar más de 16 bytes en el tipo de valor para obtener el mejor rendimiento), asignar ese pequeño espacio en el montón y desasignar, recoger basura, etc. sería muy costoso.

Cada método que ingrese, en un promedio definimos 10 tipos de valores locales para usarlo internamente, que será muy costoso en montón como tipos de referencia.

La pila puede crecer y reducirse fácilmente (no el tamaño de la pila, sino la porción de pila utilizada para el Método actual !!) ya que los tipos de valores se tratan como desplazamiento del puntero de pila, y su asignación y desasignación es fácil ya que es simple y decrememnt en stackpointer por tamaño total de todos los tipos de valor utilizados.

Donde más en el tipo de referencia, cada objeto de referencia tiene su propia asignación y tamaño, además CLR tiene que mantener la tabla de objetos que es una especie de índice de punteros reales en memoria para evitar desbordamientos de búfer. Por lo tanto, un objeto que utilice (tipo de referencia) en realidad tiene dos almacenamiento, una entrada de índice en la tabla de referencia de CLR y espacio de memoria real. Por eso es fácil y rápido almacenar tipos de valores en la pila.

+2

El tamaño de la pila realmente no puede crecer o reducirse una vez que se ha establecido para una cadena. En cambio, el puntero de pila se mueve hacia arriba o hacia abajo dependiendo de lo que está presente en la pila. Además, el boxeo no es lo que describes. El boxeo está tomando un tipo de valor y asignando un mango en el montón de GC. Esto puede causar una colección y, en promedio, no es barato. Unboxing es más rápido ya que copia el valor en el montón a la pila sin una asignación de memoria o cualquier presión de GC agregada. – codekaizen

+0

He aclarado que, por supuesto, el tamaño de la pila no crece ni se reduce, pero la parte de la pila usada para la utilización del método actual, que es el tamaño de todas las variables locales, puede crecer o reducirse. Como esta pila no es pura, tiene algunos espacios reservados para el método actual. –

+0

Sin embargo, todavía estás equivocado sobre el tema del boxeo. – codekaizen

4

Como @Akash indica, en su mayoría tiene que ver con la memoria. Durante el diseño del CLR, se observó (supongo que de la experiencia con Java) que la representación de tipos pequeños y primitivos como objetos con asas sometidas al recolector de basura causó una gran cantidad de seguimiento. Entonces los diseñadores querían un objeto "ligero" que no necesitara ser rastreado.

No hay un requisito específico en la especificación CLI para que las primitivas se asignen en pila; es un artefacto de la implementación en la máquina. El bit esencial es que el tiempo de ejecución sabe dónde se deben las instancias a la construcción de patrones de memoria bien definidos (denominados marcos) más que en el índice de objetos asignados del GC. En las máquinas x86 (y similares), esto se puede hacer de manera eficiente utilizando la pila.

2

Su afirmación no es del todo cierta. Una versión mejor: C# almacena variables locales en la pila.
Y esto no es especial ni nuevo, (casi) todos los lenguajes de programación usan la pila para variables locales y direcciones de retorno de métodos. Hay soporte para esto hasta el hardware.

Además, los tipos de valor pueden ser variables locales o campos dentro de los tipos de referencia. Entonces, los tipos de valores no siempre se almacenan en la pila. Una declaración más útil: los tipos de referencia son nunca almacenados en la pila.

Así que no se concentre en la pila demasiado muuch, es un detalle de implementación. Obtenga información sobre value- and reference-types.

12

C# no almacena nada en la pila. C# es un lenguaje de programación. Por lo tanto, una versión más correcta de su pregunta es ¿por qué el compilador C# de Microsoft emite instrucciones CIL para asignar tipos de valor en la pila?

Bueno, primero, solo a veces. Lo siguiente no van a la pila:

  1. tipos de valor que son campos de una clase
  2. tipos de valor en caja
  3. tipos de valores locales que son las variables externas de los métodos anónimos
  4. tipos de valores locales que están variables externas de bloques iteradores

En segundo lugar, cuando es posible, se hace porque es eficiente. Básicamente en el modelo de memoria CLR, en la pila, la desasignación es un relativo muy barato en comparación con la desasignación en el montón. Con los locales de tipos de valor, puede estar seguro de que nadie más, excepto el local, hará referencia a la memoria para que pueda salirse con la suya utilizando la pila en lugar del montón. Para más detalles, vea Eric Lippert.

Finalmente, lo que hace que los tipos de valor sean especiales es que tienen semántica de tipo de valor (copia por valor), y no que a veces se asignen en la pila. No hay ningún requisito en la especificación C# de que el compilador emita instrucciones para asignar tipos de valores en la pila. Lo que la especificación de C# requiere es que los tipos de valor tengan semántica de tipo de valor.

0

Para que el programa funcione correctamente, es importante que tanto las entidades de tipo valor como las de tipo clase superen cualquier referencia a ellas. Cuando se crea un objeto de clase, se crea una referencia que puede copiarse libremente en cualquier ámbito. En consecuencia, es completamente posible que las referencias al objeto continúen existiendo incluso después de que salga el alcance actual. Por el contrario, cuando se crea una variable de tipo valor, las únicas referencias que se pueden crear son de tipo efímero que desaparecerán antes de que salga el alcance actual. El hecho de que no pueda existir ninguna referencia a una variable de tipo valor cuando sale el alcance actual hace que sea seguro almacenar dichas variables en una pila.

Cuestiones relacionadas