最近的一次 问题是关于字符串 中。净抓住了我的眼睛。我知道那串的文本 拘留 因此,不同的字相同的价值是指相同的对象。我也知道,一串可以被拘留在运行时:

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

显然串被拘留在运行时驻留在堆,但我不得不假定的文字放在该程序的数据分段(和这么说我 答案 所述问题)。但是我不记得看到这种在任何地方。我猜是这种情况,因为这是我将做到这一点的事实, ldstr IL指令用于获得的文本并没有分配似乎采取的地方似乎回我。

长话短,在那里做字符串居住?是在堆中,数据分段或某些地方我还没想到的?


编辑: 如果字符串 驻留在堆,当他们分配的?

有帮助吗?

解决方案

在.NET

的字符串是参考的类型,所以它们总是在堆上(即使当它们被拘留)。您可以使用调试器验证这一点,如WinDbg的。

如果你有下面的类

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

和你打电话Foo()上的实例,您可以使用WinDbg检查堆。

在参考将最有可能被存储在一个小程序的寄存器,所以最简单的是找到参照特定的字符串是通过进行!dso。这赋予我们字符串的地址问题:

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

现在使用!gcgen找出实例是在其中生成:

0:000> !gcgen 025d2d04 
Gen 0

这是一个在零代 - 即它刚刚进行分配。谁在生根呢?

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)

在ESP是栈我们Foo()方法,但是请注意,我们有一个object[]为好。这是实习生表。让我们一起来看看。

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

我稍微降低输出,但你的想法。

<强>总之:字符串是在堆上 - 即使当他们实习。的实习表保存在堆上一个参考实例。即实习串GC过程中不收集,因为扣留表根它们。

其他提示

在Java(注册从爪哇词汇):

  

在Sun的JVM中,实习字符串(包括字符串文本)被存储在RAM的特殊池称为烫发根,其中该JVM还加载类和存储本地编译代码。然而,采访了字符串表现没有不同于已经它们被存储在普通对象堆。

纠正我,如果我错了,但不是所有对象驻留在堆中,Java和.NET?

在净,当“实习”字符串文字,存储在调用时,“实习生表”的特殊的数据结构。这是从堆和栈分开。并非所有的字符串然而拘留......我敢肯定,那些没有被保存在堆上。

不知道有关Java

我发现这对MSDN的站点有关 ldstr IL指令:

ldstr 指令推动的一个目基准(类型O)对一个新的串的对象,表示具体的字符串中存储的元数据。的 ldstr 指令 分配必要数量的记忆 并执行的任何格式转换需要转换的字符串从形式文件中使用的字符串的格式需要在运行时间。

共同的语言基础设施(CLI)保证该结果的两个ldstr说明参照两个元数据标记,有相同的字符序列返回恰恰相同的串目(一个进程称为"串的实习").

这意味着字符串,其实都是保存在该堆中。网(不同Java 指出 通过 mmyers).

在Java中,像所有对象字符串驻留在堆。 只有本地原始变量(整数,字符和引用的对象)驻留在堆栈中。

实习字符串在Java是位于一个单独的池称为字符串池中。该池由String类维护和驻留在正常堆(如上所述不彼尔姆池,其用于存储所述类的数据)。

据我所知不是所有的字符串被扣留,但调用myString.intern()返回一个从字符串池中。

保证一个字符串

参见: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally。 HTML 和javadoc的 的http:// java的。 sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern()

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top