Pergunta

A recente sobre seqüência de literais em .NET chamou minha atenção. Eu sei que strings literais são internados para que diferentes cadeias com o mesmo valor se referem ao mesmo objeto . Sei também que uma corda pode ser internado em tempo de execução:

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

Obviamente uma cadeia que está internado em reside o tempo de execução na pilha, mas eu tinha assumido que um literal é colocado no segmento de dados do programa (e disse isso na minha resposta à referida questão). No entanto eu não lembro de ter visto isso em qualquer lugar. Eu suponho que este é o caso, uma vez que é como eu faria isso eo fato de que a instrução IL ldstr é usado para obter literais e sem destinação parece ter lugar parece-me fazer backup.

Para cortar uma longa história curta, onde strings literais residem? É na pilha, o segmento de dados ou algum-lugar que eu não tenha pensado?


Editar: se strings literais não residem na pilha, quando eles estão alocados?

Foi útil?

Solução

Cordas em .NET são tipos de referência, então eles estão sempre na pilha (mesmo quando eles estão internados). Você pode verificar isso usando um depurador como o WinDbg.

Se você tem a classe abaixo

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

E você chama Foo() em uma instância, você pode usar WinDbg para inspecionar a pilha.

A referência provavelmente será armazenado em um registro para um programa pequeno, de modo que o mais fácil é encontrar a referência para a seqüência específica é fazendo um !dso. Isso nos dá o endereço de nossa string em questão:

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[])

Agora uso !gcgen para descobrir qual geração a instância está em:

0:000> !gcgen 025d2d04 
Gen 0

É na geração de zero - ou seja, que acaba de ser alocado. Quem está torcendo-lo?

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)

O ESP é a pilha para o nosso método Foo(), mas aviso que temos uma object[] também. Essa é a tabela interna. Vamos dar uma olhada.

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

Eu reduzi a saída um pouco, mas você começa a idéia.

Em conclusão : cordas são na pilha - mesmo quando eles estão internados. A tabela internados contém uma referência para a instância na pilha. Ou seja, cordas internados não são recolhidos durante GC porque a tabela internados raízes deles.

Outras dicas

Em Java (a partir do Java Glossário ):

O In Sun JVM, as cordas internados (que inclui literais String) são armazenados em uma piscina especial de RAM chamado de perm gen, onde os JVM também carrega as classes e lojas nativamente código compilado. No entanto, as cordas intered se comportam de maneira diferente do que tinham sido armazenados no heap objeto comum.

me corrija se eu estiver errado, mas não todos os objetos residem na pilha, em Java e .NET?

Na Net, strings literais quando "internado", são armazenados em uma estrutura de dados especial chamado, a "mesa estagiário". Esta é separada da pilha e a pilha. Nem todas as cordas estão internados no entanto ... Eu tenho certeza que aqueles que não são são armazenadas na pilha.

Não sei sobre Java

Eu encontrei isso no site do MSDN sobre o ldstr IL instrução :

A instrução ldstr empurra uma referência de objeto (tipo O) para um novo objeto string representando o literal cadeia específica armazenada nos metadados. A instrução ldstr aloca a quantidade necessária de memória e executa qualquer conversão de formato necessária para converter o literal de cadeia da forma usada no arquivo para o formato de cadeia obrigatório em tempo de execução.

O Common Language Infrastructure (CLI) garante que o resultado de duas instruções ldstr referentes a dois tokens de metadados que têm a mesma sequência de caracteres voltar precisamente o mesmo objeto string (um processo conhecido como "string internar").

Isto implica que as strings literais são na verdade armazenadas no heap em .NET (ao contrário de Java como apontou por mmyers ).

Em Java, strings como todos os objetos residem no heap. Apenas variáveis ??primitivas locais (ints, caracteres e referências a objetos) residem na pilha.

internado Cordas está em java estão localizados em um pool separado chamado o conjunto de cadeia. Esta associação é mantido pela corda classe e reside na pilha normal (não a piscina Perm como mencionado acima, que é usada para armazenar os dados da classe).

Como eu o compreendo nem todas as cordas estão internados, mas chamando myString.intern () retorna um String que é garantida a partir do exterior da cadeia.

Veja também: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally. html e o javadoc http: // java. sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern ()

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top