Frage

Eine aktuelle Frage zu Stringliterale in .NET fing mein Auge. Ich weiß, dass Stringliterale werden interniert , so dass verschiedene Strings mit dem gleichen Wert auf das gleiche Objekt beziehen . Ich weiß auch, dass eine Zeichenfolge zur Laufzeit interniert werden:

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

Offensichtlich eine Zeichenfolge, die zur Laufzeit interniert wird auf dem Heap befindet, aber ich hatte angenommen, dass ein wörtliche im Programmdatensegment platziert wird (und das so in meinem Antwort auf die Frage). Allerdings erinnere ich mich nicht über diese überall zu sehen. Ich gehe davon aus das der Fall ist, da es, wie ich es tun würde, und die Tatsache, dass die ldstr IL Anweisung Literale zu bekommen verwendet wird und keine Zuordnung scheint zu stattzufinden scheint mich zu sichern.

eine lange Geschichte kurz zu machen, wo wohnen Stringliterale? Ist es auf dem Heap, das Datensegment oder einen Teil-Platz habe ich nicht gedacht?


Edit: Wenn Stringliterale Sie residieren auf dem Heap, wenn sie zugeordnet?

War es hilfreich?

Lösung

Strings in .NET sind Referenztypen, so dass sie immer auf dem Heap (auch wenn sie interniert werden). Sie können dies mit einem Debugger überprüfen wie WinDbg.

Wenn Sie die Klasse unter

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

Und Sie nennen Foo() auf einer Instanz, können Sie WinDbg verwenden, um die Haufen zu untersuchen.

Die Referenz wird höchstwahrscheinlich in einem Register für ein kleines Programm gespeichert werden, so ist die einfachste der Verweis auf die spezifische Zeichenfolge zu finden, ist durch einen !dso tun. Dies gibt uns die Adresse unserer Zeichenfolge in Frage:

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

Jetzt verwenden !gcgen, um herauszufinden, welche Generation die Instanz in:

0:000> !gcgen 025d2d04 
Gen 0

Es ist in Generation Null - das heißt, es nur zugewiesen werden muss. Wer Verwurzelung es?

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)

Das ESP ist der Stapel für unsere Foo() Methode, aber feststellen, dass wir eine object[] auch haben. Das ist der intern Tisch. Lassen Sie uns einen Blick darauf werfen.

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

I reduziert die Ausgabe etwas, aber Sie bekommen die Idee.

Fazit : Saiten auf dem Heap sind - auch wenn sie interniert werden. Die Internierung Tabelle enthält einen Verweis auf die Instanz auf dem Heap. D. h internierten Strings werden nicht während der GC, weil die Internierung Tabelle Wurzeln sie gesammelt werden.

Andere Tipps

In Java (aus der Java Glossar ):

  

In Sun JVM, die internierten Strings (die Stringliterale enthält) wird in einem speziellen Pool von RAM gespeicherte zul gen genannt, wo die JVM auch lädt Klassen und speichert nativ kompilierten Code. Allerdings verhalten sich die intered Strings nicht anders, als man sie im normalen Objektheap gespeichert.

mich korrigieren, wenn ich falsch bin, aber nicht alle Objekte befinden sich auf dem Heap, sowohl in Java und .NET?

In .Net, Stringliterale wenn „interniert“ werden in einer speziellen Datenstruktur gespeichert genannt, die „intern Tisch“. Dies ist unabhängig von dem Heap und Stack. Nicht alle Saiten jedoch interniert sind ... Ich bin mir ziemlich sicher, dass diejenigen, die nicht auf dem Heap gespeichert.

Sie wissen nicht, über Java

fand ich diese auf MSDN-Website über die ldstr IL Anweisung :

  

Die ldstr Anweisung drückt eine Objektreferenz (Typ O) zu einem neuen String-Objekt, das die spezifische Stringliteral in den Metadaten gespeichert. Die Anweisung ldstr ordnet die erforderliche Menge an Speichern und führt jede Formatumwandlung erforderlich, um den Stringliteral aus der Form, in der Datei in das Zeichenfolgenformat während der Laufzeit erforderlich verwendet zu konvertieren.

     

Die Common Language Infrastructure (CLI) garantiert, dass das Ergebnis von zwei ldstr Anweisungen zu zwei Metadaten-Token beziehen, die die gleiche Abfolge von Zeichen zurückgeben genau das gleiche String-Objekt (einen Prozess, bekannt als „string Internierung“).

Dies bedeutet, dass die Zeichenfolgenliterale in der Tat auf dem Heap in .NET (im Gegensatz zu Java als wies darauf hin, von mmyers ).

In Java-Strings wie alle Objekte befinden sich in dem Haufen. Nur lokale primitive Variablen (Ints, Zeichen und Verweise auf Objekte) befinden sich im Stapel.

Interned String ist in Java befinden sich in einem separaten Pool der String-Pool genannt. Dieser Pool wird von der String-Klasse gehalten und befindet sich auf dem normalen Heap (nicht der Perm-Pool wie oben erwähnt, dass zum Speichern der Klassendaten verwendet wird).

Wie ich verstehe es nicht alle Strings werden interniert, aber Aufruf myString.intern () gibt einen String, der aus dem String-Pool gewährleistet ist.

Siehe auch: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally. html und die javadoc http: // java. sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern ()

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top