Ограничение памяти по умолчанию для стека в 64-разрядной версии Windows составляет 4 МБ. Таким образом, вы будете в безопасности с выделением не более 3 МБ.

к ответь насчет кучи и стека, у меня возник вопрос: почему важно знать, где расположены переменные?

другой ответ кто-то указал, что стек быстрее. Это единственный вывод? Может ли кто-нибудь привести пример кода, в котором простое изменение местоположения может решить проблему (например, производительность)?Обратите внимание, что этот вопрос специфичен для .NET

1 вопрос снят с ТА.

Примечание для будущих пользователей Google,

 MickyD29 мар. 2015 г., 04:06
первая ссылка в этом C # вопроссломанный (как указано) ивторая ссылка около а такжеstack allocation in generalне относится к .NETКак указал Уоррен П с его 66 полезными голосами (на момент написания статьи):.
 MickyD29 мар. 2015 г., 04:12
Разве это нехорошо указывать на то, что успех современных языков «управляемого кода» - это то, что понимание стека и кучи больше не нужно (очень) для разработчиков на C # и Java, потому что те из нас, кому приходится отлаживать то, что мы сделали неправильно в C и C ++ нужно было понять модель, чтобы мы могли исправить наш код, когда он сломался. Другими словами, «невежество - это сила», потому что абстракция работает так, как задумано, что позволяет мне работать на виртуальной машине, которую проще использовать, чем на реальной."До тех пор, пока вы знаете, что такое семантика, единственными последствиями стека и кучи являются то, что вы не переполняете стек и не забываете, что с сборкой мусора связана стоимость."

Ответы на вопрос(7)

Мой первоначальный ответ содержал упрощенное «структуры распределяются в стеке» и немного сбивало с толку stack-vs-heap и value-vs-reference, поскольку они связаны в C #. Находятся ли объекты в стеке или нет, это деталь реализации, которая не очень важна. Джон уже объяснил это хорошо. При выборе между использованием класса и структуры более важно понимать, что ссылочные типы работают иначе, чем типы значений. Возьмем следующий простой класс в качестве примера:)

Теперь рассмотрим следующий код:

public class Foo
{
   public int X = 0;
}

В этом примере foo и foo2 являются ссылками на один и тот же объект. Установка X на foo2 также повлияет на foo1.

Foo foo = new Foo);
Foo foo2 = foo;
foo2.X = 1;

Если мы изменим класс Foo на struct, то это уже не так, Это потому, что структуры не доступны через ссылки. Назначение foo2 фактически сделает копию.Одна из причин размещения содержимого в стеке заключается в том, что сборщик мусора не должен его очищать. Обычно вы не должны беспокоиться о таких вещах; просто используйте классы! Современные сборщики мусора делают довольно хорошую работу. Некоторые современные виртуальные машины например, Java 1.6) могут даже

определить, безопасно ли размещать объекты в стеке даже если они не являются типами значений.Хотя ваш пример и объяснение верны, вы продемонстрировали контрпример к первому предложению. Что такое "Foo.X"? Int, который является типом значения - и все же он всегда живет в куче. Утверждение «классы распределяются в куче, структуры распределяются в стеке» - это упрощение.

 Jon Skeet25 янв. 2009 г., 08:41
Лучше было бы сказать, что типы значений размещаются там, где они объявлены. Если они объявлены как локальные переменные в функции, они находятся в стеке. Если они объявлены как члены в классе, они в куче, как часть этого класса.
 jalf25 янв. 2009 г., 10:45
Я не буду голосовать за этот ответ, потому что он сочетает в себе значения ссылок и значений со значениями кучи и стека.
 Jader Dias25 янв. 2009 г., 13:40
Спасибо за исправление, это вызвало "Ага!" момент. Теперь я понимаю, что stack-vs-heap является относительно незначительной деталью реализации в C #, и что значение-vs-reference является реальной проблемой здесь. Я должен был объяснить это так.
 Wim Coenen25 янв. 2009 г., 15:00
теперь я проголосовал за твои исправления
 Jader Dias25 янв. 2009 г., 15:30
Я думаю, что самая простая причина заключается в том, что если он находится в куче, сборщик мусора должен иметь дело с переменной, когда она больше не нужна. Находясь в стеке, переменная отбрасывается тем, кто ее использовал, например, методом, который ее создавал.
Решение Вопроса

мог обратите внимание на то, что вновь созданный объект никогда не использовался вне текущего метода (ссылка никогда не могла бы выйти в другом месте), и разместите его в стеке. В данный момент этого не происходит, но это будет законно.Аналогично компилятор C #

мог решите выделить все локальные переменные в куче - стек будет просто содержать ссылку на экземпляр MyMethodLocalVariables, и через него будет реализован весь доступ к переменным. (На самом деле, переменные, захваченные делегатами или блоками итераторов, уже ведут себя подобным образом.)Ваш вопрос возник, когда Эрик Липперт рассматривал C # в глубине - у меня есть раздел, объясняющий, что происходит в C # 1, и он рассчитывал, что

разработчики не должны заботитьсяЭрик - мужчина. Вам повезло иметь такого хорошего рецензента..

 RichardOD09 мар. 2010 г., 11:21
редактировать:

ни медленным, чем доступ к области памяти в стеке. Есть несколько соображений, которые могут, в некоторых случаях, поддерживать утверждение о том, что доступ к памяти в расположениях стека в целом быстрее, чем доступ к памяти в расположениях кучи. Из их:В стеке локальность временного распределения (распределения, сделанные близко друг к другу во времени) подразумевает пространственную локальность (хранилище, которое близко друг к другу в пространстве). В свою очередь, когда локальность временного выделения подразумевает локальность временного доступа (доступ к объектам, выделенным вместе, осуществляется совместно), хранилище с последовательным стеком имеет тенденцию работать лучше в отношении кэшей ЦП и систем подкачки операционной системы.

Плотность памяти в стеке имеет тенденцию быть выше, чем в куче из-за издержек ссылочного типа. Более высокая плотность памяти часто приводит к лучшей производительности, например, потому что больше объектов помещается в кэш CPU.Стеки потоков имеют тенденцию быть довольно маленькими - максимальный размер стека по умолчанию в Windows составляет 1 МБ, и большинство потоков обычно используют только несколько страниц стека. В современных системах стеки всех потоков приложений могут помещаться в кэш ЦП, что делает типичный доступ к объектам стека чрезвычайно быстрым. (С другой стороны, целые кучи редко помещаются в кэш процессора).С учетом сказанного вам не следует перемещать все свои выделения в стек! Стеки потоков в Windows ограничены, и стек легко исчерпать, применяя неразумную рекурсию и большие выделения стеков.

Это имеет смысл, и я очень ценю, что вы нашли время, чтобы дать такой подробный ответ!

 Dave Black13 мар. 2019 г., 21:18
только для 32-битных процессов. 64-разрядный процесс Windows имеет размер стека по умолчанию 4 МБ.Я много играл с разными бенчмарками в стеке и куче, и я бы сделал следующие выводы:
 Elham Azadfar21 июн. 2018 г., 16:49
Часть этого ответа является неполной. Ответ гласит: «... максимальный размер стека по умолчанию в Windows составляет 1 МБ». Это правда

небольшие приложения (не слишком много объектов в куче)

объекты размером <1 КБСлегка лучшая производительность стека для

 (1x - 5x быстрее)Объекты размером от 1КБ до 100КБ

Гораздо лучшая производительность для

 (до 100 раз быстрее или даже больше)Большое количество предметов

Большое давление памяти - много выделений в секунду и полная памятькрупные объекты 10 КБ - 3 МБ (я полагаю, системы x64)XBox (медленный сборщик мусора)Лучший подход - объединение массивов. Это быстро, как стек, но у вас нет такого ограничения, как со стеком.

Еще одним следствием использования стека является то, что он является поточно-ориентированным благодаря desing.

Ограничение памяти по умолчанию для стека в 64-разрядной версии Windows составляет 4 МБ. Таким образом, вы будете в безопасности с выделением не более 3 МБ.

Последствия размещения кучи и стека (

азмещаются в стеке. Исключение составляют случаи, когда тип значения является частью ссылочного типа, и в этом случае он размещается в куче вместе с ссылочным типом. То есть дизайнер типа принимает это решение от имени пользователей.

В таких языках, как C или C ++, пользователь может решить, где размещать данные, и для некоторых особых случаев это может быть значительно быстрее выделять из стека по сравнению с выделением из кучи.

Это связано с тем, как обрабатываются выделения кучи для C / C ++. На самом деле в .NET распределение кучи происходит довольно быстро (за исключением случаев, когда он запускает сборщик мусора), поэтому, даже если вы решите, куда распределить, я думаю, что разница не будет существенной.

Однако, поскольку куча мусора собирается, а стек - нет, очевидно, в некоторых случаях вы увидите некоторые различия, но это вряд ли уместно, учитывая тот факт, что у вас нет выбора в .NET.

Спасибо за это фундаментальное замечание:

 Veverke18 июл. 2016 г., 14:46
В .NET мало что можно обсуждать, поскольку не пользователь типа решает, где размещать экземпляры, в то время как в таких языках, как C или C ++, пользователь может решать, где размещать данные, а в некоторых особых случаях это может быть значительно быстрее. выделить из стека по сравнению с выделением из кучи.На мой взгляд, знание о различиях между стеком и кучей и о том, как на нем размещаются объекты, может быть очень полезным, когда вы действительно задумаетесь о производительности вашего приложения. Следующие вопросы делают необходимым понять различия: Как вы думаете, что быстрее и эффективнее для доступа .NET? - стек или куча. В каких сценариях .NET может размещать тип значения кучи?

поскольку не пользователь типа решает, где размещать экземпляры.

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

Ваш ответ на вопрос