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

Где хранятся все статические элементы?

Я пытаюсь узнать, как С# управляет памятью. Я застрял на статических элементах, я читал многочисленные блоги и статьи на эту тему, но я не могу найти вполне удовлетворительный ответ.

Определите блок кода, который поможет найти ответ.

class myClass
{
    static string myStr = "String Data";
    static int myInt = 12;
}

Прежде чем вы, ребята, поделитесь своим ответом, позвольте мне поделиться своими выводами, что знаю об этом предмете. Не стесняйтесь соглашаться или не соглашаться и помогать мне найти правильный ответ.

  • Статичность только для жизни.
  • Статический ссылочный тип (myStr), будет продолжаться в кучу в течение жизненного цикла.
  • Статический тип значения (myInt), будет идти в стек, для жизни.

Что меня смущает, некоторые ответы, которые я нашел в Интернете, по этому вопросу.

Путаница № 1:

Когда ваша программа запускается, она загружает все связанные сборки в AppDomain. Когда сборка загружается, вызывается все статические конструкторы, включая статические поля. Они будут жить там, и единственный способ их разгрузить - выгрузить AppDomain.

В приведенных выше строках явно указано, что все статические элементы хранятся в AppDomain. Тогда почему все в Интернете говорят, что элементы "Статические" хранятся в куче/стеке?

Путаница № 2:

Каждая статическая переменная сохраняется в куче независимо от того, объявлена ​​ли она в ссылочном типе или типе значения.

Если каждая статическая переменная хранится в куче. Тогда почему некоторые люди говорят, что статическая переменная типа значения хранится в стеке?

Пожалуйста, помогите соединить мои точки, чтобы понять управление памятью статических переменных в С#. Большое вам спасибо за ваше драгоценное время:)

4b9b3361

Ответ 1

Во-первых, обратите внимание, что все это детализация реализации. Единственное, что гарантирует время выполнения:

  • Когда вы запрашиваете статическое поле, оно там
  • Статический конструктор выполняется в какой-то момент, прежде чем использовать тип

Это в значительной степени. Все остальное является детальностью реализации - спецификация не заботится о стеке, куче или чем-то еще. Это зависит от реализации среды выполнения, и допустимая среда выполнения может помещать все в стек, если это того пожелает, или в кучу. И не забывайте регистры.

Теперь рассмотрим некоторые из заблуждений, которые вам уже удалось подобрать:

  • Статика - это просто на всю жизнь - да. Он ничего не говорит о том, когда и где он хранится, - только это доступно, когда вы его просили. Соответствующая среда исполнения может свободно использовать любую память, которую она хочет, или даже никогда не загружать поля в памяти (например, сохраняя их в изображении, которое уже находится в памяти).
  • Статика будет идти на кучу, для жизни - скорее всего, да. Но это не часть спецификации, и совместимая среда исполнения может хранить ее там, где она хочет, или вообще нигде, если будут соблюдаться надлежащие гарантии. Кроме того, не забывайте, что "для жизни" означает "по крайней мере, для жизни AppDomain"; он может быть или не быть освобожден, когда домен будет выгружен.
  • Статический тип значения будет отображаться в стеке, для жизни - скорее всего, нет. Опять же, деталь реализации, но стек имеет совершенно другую семантику, чем то, что имеет смысл для статического значения. И следующий момент даст вам больше причин, по которым:
  • При загрузке assambly вызываются все статические конструкторы, включая статические поля. - Нет. Нет такого требования, и такой гарантии нет. Если вы полагаетесь на это, ваша программа будет ломаться (и я видел это много раз раньше). Опять же, деталь реализации, но в текущих реализациях MSCLR, статика, как правило, выделяется в кучу своей, а некоторое время до того, как тип, который они определены, необходим. Вы можете легко увидеть это, если вы выбросите исключение в статическом конструкторе - это вызовет TypeLoadException, скорее всего, в методе, который сначала ссылается на тип (само собой разумеется, это может сделать сложную статизацию отладки).
  • Типы ссылок идут в кучу, типы значений идут в стек. - Нет. Это путает механизм с семантикой. Единственная разница между ними - их семантика - все остальное зависит от реализации. Если среда выполнения может сохранять ссылочную семантику для ссылочных типов в стеке, это совершенно верно. И даже при текущих моделях MSCLR значения типов хранятся в куче все время - всякий раз, когда они помещаются в бокс или члены ссылочного типа, например.

Некоторые люди могут быть смущены. Некоторые не понимают разницу между контрактом и практическими реализациями. Некоторые просто не знают, о чем они говорят. Хотелось бы, чтобы был простой способ узнать, что есть, но нет. Если вы сомневаетесь, вы можете перейти к спецификациям С#/CLR, но это говорит только о контракте, а не о практической реальности.

Весь смысл управляемой памяти заключается в том, что вы не должны заботиться об этих деталях реализации. Конечно, как и любая абстракция, она течет - и имеет смысл знать, как это происходит на самом деле, вплоть до микроинструкций процессора, кэширования памяти и т.д. Через все уровни и абстракции. Но на это не на что положиться - реализация может измениться в любое время, и она имеет много раз в прошлом.

Ответ 2

Всякий раз, когда процесс загружается в ОЗУ, мы можем сказать, что память грубо разделенный на три области (в рамках этого процесса): стек, куча, и Static (который, в .NET, на самом деле является особой областью внутри кучи известный только как высокочастотная куча).

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

Подробнее здесь.

Ответ 3

Существует экземпляр класса, созданного с инициализацией всех статических элементов.

Члены статических классов обычно хранятся в куче, члены типов значений обычно хранятся в стеке.

Это не обязательно так, вы можете прочитать этот блог для получения дополнительной информации.

Это от одного из разработчиков языка от С#, Эрика Липперта.

Блог показывает, что он, вопреки нормальным знаниям, не уверен, что типы значений находятся в стеке, а ссылочные типы находятся в куче, но они обычно есть.

Он просто не указан в спецификации.

Ответ 4

Каждая статическая переменная сохраняется в куче независимо от того, объявлена ​​ли она в ссылочном типе или типе значения. Всего всего один слот независимо от того, сколько экземпляров создано. (Там не обязательно должны быть экземпляры, созданные для того, чтобы один слот существовал, хотя.)

Кроме того, когда статическая переменная выделена, она будет сохранена как часть Methodtable. Методические средства. Когда класс загружается впервые в приложении, отдельная память будет выделена в appdomain для переменных уровня класса и методов внутри класса..

Если статическая переменная является примитивным типом, она будет сохранена как часть Methodtable. Если это ссылочный тип, он будет храниться внутри кучи, и ссылка будет сохранена в Methodtable.