C # ссылка на переменную распределение памяти - PullRequest
5 голосов
/ 29 января 2009

Кто-нибудь знает, сколько памяти занято при создании переменной ссылочного типа?

String s = "123";

Сколько памяти будет занимать в качестве ссылки, а не данные, указывающие на него?

Ответы [ 5 ]

12 голосов
/ 29 января 2009

Это разбивается следующим образом:

String s = "123";

Переменная s: это будет использовать собственный размер указателя на текущей архитектуре (которая считается 32-битной, если ОС 32-битная или процесс выполняется под WoW64), поэтому 32 бита или 64 бита соответственно. В этом случае s либо находится в стеке, либо зарегистрирован. Если бы вы поместили строковую ссылку в массив, тогда это пространство было бы использовано в куче.

Тот факт, что строка является объектом: 8 байтов служебных данных разделены на 4 байта для таблицы методов, которая удваивается как указание того, какой фактический тип является объектом, плюс 4 байта для некоторых служебных битов и синхронизирующий блок, который позволяет использовать его в качестве цели оператора блокировки.

Строка всегда заканчивается нулевым символом (хотя это деталь реализации, не являющаяся частью контракта среды выполнения), так что ее можно использовать непосредственно со строкой apis в стиле C, символы UTF-16, поэтому два байта на символ в смысле .Net использует символ (подробности того, почему это сложно и требует перехода к Unicode, я опущу).

Строки дополнительно содержат следующее:

Версии .Net до 4.0

  • int для длины строки в символах
  • int для длины базового массива, содержащего символы
  • символ, который является первым символом в строке (последующие символы идут сразу после него) или нулевой символ для пустой строки

Строка может потреблять вдвое больше памяти, необходимой для фактического хранения массива символов, необходимого в соответствии со способом работы StringBuilder

Таким образом, сама строка будет занимать от 16 + (2 * n) + 2 до 16 + (4 * n) + 2 байта в куче в зависимости от того, как она была создана.

Версии .Net начиная с 4.0 и выше

  • int для длины строки в символах
  • символ, который является первым символом в строке (последующие символы идут сразу после него) или нулевой символ для пустой строки

Сама строка будет занимать как минимум 12 + (2 * n) + 2 байта в куче.


Обратите внимание, что в обоих случаях строка может занимать немного больше фактического пространства, чем она использует, в зависимости от того, какое выравнивание применяет среда выполнения, это, вероятно, будет не больше, чем IntPtr.Size.

Это может быть еще сложнее из-за интернирования строк (когда два отдельных экземпляра в конечном итоге указывают на одну и ту же строку, так как она неизменна), поскольку теоретически вы должны разделить служебные данные кучи (плюс служебные данные интерна) на число «независимых» ссылки на строку.

для дальнейшего обсуждения этого взгляните на эту статью . Однако обратите внимание, что эта статья устарела для изменений в 4.0.

10 голосов
/ 29 января 2009

Размер самой ссылки будет зависеть от архитектуры вашего процессора - 4 байта на 32-битной, 8 байтов на 64-битной.

4 голосов
/ 29 января 2009

В зависимости от того, используете ли вы 32- или 64-разрядную машину, это будет 32- или 64-разрядный указатель.

1 голос
/ 29 января 2009

Если вы хотите проверить это в коде, позвоните:

IntPtr.Size
1 голос
/ 29 января 2009

Обычно требуется 4 байта для справки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...