2011-03-09 38 views
12

我正在使用SOS調試擴展dll檢查字符串類型的內存佈局。結果如下。.NET在哪裏放置String值?

!DSO

ESP/REG Object Name 

0015EFC0 01c6b9cc System.String hello,world 

!做01c6b9cc

Name:  System.String 

MethodTable: 6de3f9ac 

EEClass:  6db78bb0 

Size:  36(0x24) bytes 

File:  C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089>\mscorlib.dll 

String:  hello,world 

Fields: 
     MT Field Offset     Type VT  Attr Value Name 

6de42978 40000ed  4   System.Int32 1 instance  11 m_stringLength 

6de41dc8 40000ee  8   System.Char 1 instance  68 m_firstChar 

6de3f9ac 40000ef  8  System.String 0 shared static Empty 

    >> Domain:Value 00331488:01c61228 << 

現在我想知道,究竟哪裏是字符串值 「Hello World」 的存儲?

謝謝。

+0

我猜可能是一個'char []'在堆上的其他地方。 – Joey 2011-03-09 03:36:55

回答

12

在m_firstChar。堆分配足夠大以適應整個字符串,而不僅僅是第一個字符。易於在Visual Studio中看到:

class Program { 
    static void Main(string[] args) { 
     string s = "hello" + "world"; 
    } // <=== Breakpoint here 
} 

當斷點碰到時,使用Debug + Windows + Memory + Memory1。在地址框中鍵入s。你會看到:

0x01B3F6BC e8 0a 67 6e 0b 00 00 00 0a 00 00 00 68 00 65 00 è.gn........h.e. 
0x01B3F6CC 6c 00 6c 00 6f 00 77 00 6f 00 72 00 6c 00 64 00 l.l.o.w.o.r.l.d. 
  • 的對象開始在地址 - 4,syncblk存儲有(不可見)。
  • 接下來的4個字節是方法表指針(0x6e670ae8,又名類型句柄)。
  • 接下來的4個字節是m_arrayLength成員,字符串的分配大小(0x0b)。
  • 接下來的4個字節是m_stringLength成員,即字符串中實際字符數(0x0a)。
  • 下一個字節存儲字符串,從m_firstChar開始。

這是針對.NET 3.5 SP1的。您將不會在.NET 4.0及更高版本中看到m_arrayLength成員,該字段已被刪除。

+0

感謝您的解釋。我不知道爲什麼我沒有注意到昨天m_firstChar ...另外,我正在使用.NET 4.0。 – smwikipedia 2011-03-10 02:24:54

+3

好吧,解釋它,.NET 4.0刪除了m_arrayLength字段。 – 2011-03-10 02:26:58

3

就像一個C「字符串」,它存儲在m_stringLength字節開始於m_firstChar這是一個不安全的指針,而不是一個實際的字符。雖然C#使用長度前綴字符串而不是null

這就是說,CLR的美妙之處在於你不需要關心。這如何成爲一個問題?

+0

m_firstChar不是一個指針。字符串的字符嵌入在字符串對象中,從m_firstChar開始。 – 2011-03-09 15:59:03

+0

@Hans所以我從你的答案中看到,但這是如何工作的?不要物體需要固定的長度? – 2011-03-09 20:50:02

+0

沒有這樣的要求。最好的例子是一個數組。然而,這些都是CLR可以玩的技巧,但對我們來說卻並不可用。 – 2011-03-09 20:57:54