Подтвердить что ты не робот

Где .NET помещает значение String?

Я использую расширение SOS для отладки dll, чтобы проверить структуру памяти типа String, и ниже приведен результат.

! DSO

ESP/REG  Object   Name

0015EFC0 01c6b9cc System.String    hello,world

! do 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"?

Благодарю.

4b9b3361

Ответ 1

В 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, aka type handle).
  • Следующие 4 байта - это член m_arrayLength, выделенный размер строки (0x0b).
  • Следующие 4 байта - это член m_stringLength, фактическое количество символов в строке (0x0a).
  • Следующие байты хранят строку, начиная с m_firstChar.

Это для .NET 3.5 SP1. Вы не увидите элемент m_arrayLength в .NET 4.0 и выше, поле было удалено.

Ответ 2

Как строка C ", она хранится в байтах m_stringLength, начиная с m_firstChar, который является небезопасным указателем, а не фактическим символом. С# использует строчную префиксную строку, а не null с разделителем.

Тем не менее, красота CLR заключается в том, что вам не нужно заботиться. Как это стало проблемой?