Pregunta

cadena literales en .NET me llamó la atención. Yo sé que los literales de cadena se internados de manera que diferentes cadenas con el mismo valor se refieren al mismo objeto . También sé que una cadena puede ser internada en tiempo de ejecución:

string now = DateTime.Now.ToString().Intern(); 

Obviamente una cadena que se internada en tiempo de ejecución reside en el montón pero había asumido que un literal se coloca en el segmento de datos del programa (y dicho por lo que en mi respuesta a dicha pregunta ). Sin embargo, yo no recuerdo haber visto esto en cualquier lugar. Asumo que este es el caso, ya que es la forma en que lo haría y el hecho de que la instrucción ldstr IL se utiliza para obtener literales y de asignación parece tener lugar me parece una copia de seguridad.

Para no hacer el cuento largo, ¿de dónde residen los literales de cadena? Es que en el montón, el segmento de datos o algún lugar que no he pensado?


Editar: si los literales de cadena DO residir en el montón, cuando se asignan?

¿Fue útil?

Solución

Las cadenas en .NET son los tipos de referencia, por lo que son siempre en el montón (incluso cuando están internados). Esto se puede comprobar mediante un depurador como WinDbg.

Si usted tiene la clase de abajo

   class SomeType {
      public void Foo() {
         string s = "hello world";
         Console.WriteLine(s);
         Console.WriteLine("press enter");
         Console.ReadLine();
      }
   }

Y se llama a Foo() en una instancia, puede utilizar WinDbg para inspeccionar el montón.

La referencia más probable que se almacena en un registro para un programa pequeño, por lo que el más fácil es encontrar la referencia a la cadena específica es haciendo un !dso. Esto nos da la dirección de nuestra cadena en cuestión:

0:000> !dso
OS Thread Id: 0x1660 (0)
ESP/REG  Object   Name
002bf0a4 025d4bf8 Microsoft.Win32.SafeHandles.SafeFileHandle
002bf0b4 025d4bf8 Microsoft.Win32.SafeHandles.SafeFileHandle
002bf0e8 025d4e5c System.Byte[]
002bf0ec 025d4c0c System.IO.__ConsoleStream
002bf110 025d4c3c System.IO.StreamReader
002bf114 025d4c3c System.IO.StreamReader
002bf12c 025d5180 System.IO.TextReader+SyncTextReader
002bf130 025d4c3c System.IO.StreamReader
002bf140 025d5180 System.IO.TextReader+SyncTextReader
002bf14c 025d5180 System.IO.TextReader+SyncTextReader
002bf15c 025d2d04 System.String    hello world             // THIS IS THE ONE
002bf224 025d2ccc System.Object[]    (System.String[])
002bf3d0 025d2ccc System.Object[]    (System.String[])
002bf3f8 025d2ccc System.Object[]    (System.String[])

Ahora utilice !gcgen para averiguar qué generación es la instancia en:

0:000> !gcgen 025d2d04 
Gen 0

Es en la generación cero - es decir, que acaba de ser asignado. ¿Quién enraizándolo?

0:000> !gcroot 025d2d04 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 1660
ESP:2bf15c:Root:025d2d04(System.String)
Scan Thread 2 OSTHread 16b4
DOMAIN(000E4840):HANDLE(Pinned):6513f4:Root:035d2020(System.Object[])->
025d2d04(System.String)

El ESP es la pila para nuestra object[] método, pero aviso que tenemos un <=> también. Esa es la tabla interna de. Vamos a echar un vistazo.

0:000> !dumparray 035d2020
Name: System.Object[]
MethodTable: 006984c4
EEClass: 00698444
Size: 528(0x210) bytes
Array: Rank 1, Number of elements 128, Type CLASS
Element Methodtable: 00696d3c
[0] 025d1360
[1] 025d137c
[2] 025d139c
[3] 025d13b0
[4] 025d13d0
[5] 025d1400
[6] 025d1424
...
[36] 025d2d04  // THIS IS OUR STRING
...
[126] null
[127] null

reduje la salida un poco, pero se entiende la idea.

En conclusión : Las cadenas están en el montón - incluso cuando están internados. La tabla de internación contiene una referencia a la instancia en el montón. Es decir. cuerdas internados no se recogen durante GC porque la tabla raíces internados ellos.

Otros consejos

En Java (de la Java Glosario ):

  

En la JVM de Sun, las cuerdas internados (que incluye literales de cadena) se almacenan en una piscina especial de RAM llama la permanente generación, donde la JVM también carga las clases y las tiendas de forma nativa código compilado. Sin embargo, las cadenas InteRed se comportan de manera diferente que si se hubieran almacenado en el objeto pila ordinaria.

Corrígeme si estoy equivocado, pero no todos los objetos residen en el montón, tanto en Java y .NET?

En .Net, literales de cadena cuando "internados", se almacenan en una estructura de datos especial que se llama, la "mesa interno". Esto es independiente de la pila y la pila. No todas las cadenas están internados sin embargo ... Estoy bastante seguro de que los que no lo son se almacenan en el montón.

No sabe acerca de Java

He encontrado esto en el sitio de MSDN acerca de la ldstr instrucción IL :

  

La instrucción <=> empuja una referencia de objeto (tipo O) a un nuevo objeto cadena que representa la cadena específica literal almacenado en los metadatos. La instrucción <=> asigna la cantidad necesaria de memoria y realiza ninguna conversión del formato requerido para convertir la cadena literal de la forma utilizada en el archivo en el formato de cadena requerida en tiempo de ejecución.

     

El Common Language Infrastructure (CLI) garantiza que el resultado de dos instrucciones ldstr referencia a dos fichas de metadatos que tienen la misma secuencia de caracteres de retorno precisamente el mismo objeto de cadena (un proceso conocido como "cadena de internación").

Esto implica que los literales de cadena son, de hecho, almacenados en el montón en .NET (a diferencia de Java como señaló por mmyers ).

En Java, cadenas como todos los objetos residen en el montón. Sólo las variables primitivas locales (chars intercepciones, y las referencias a objetos) residen en la pila.

Interned cadena de Java se encuentran en una piscina separada llamada el grupo de cadena. Esta piscina es mantenido por la clase String y reside en el montón normal (no la piscina Perm como se mencionó anteriormente, que se utiliza para almacenar los datos de la clase).

A mi entender no están internados todas las cadenas, pero myString.intern llamando al () devuelve una cadena que está garantizado desde el grupo de cadena.

Vea también: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally. html y el Javadoc http: // java. sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern ()

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