Вопрос

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

  • Где и что они (физически в памяти реального компьютера)?
  • В какой степени они контролируются ОС или средой выполнения языка?
  • Какова их сфера применения?
  • Что определяет размер каждого из них?
  • Что делает человека быстрее?
Это было полезно?

Решение

Стек — это память, выделенная в качестве рабочего пространства для потока выполнения.При вызове функции в верхней части стека резервируется блок для локальных переменных и некоторых бухгалтерских данных.Когда эта функция возвращает значение, блок становится неиспользуемым и его можно использовать при следующем вызове функции.Стек всегда резервируется в порядке LIFO (последний пришел — первый ушел);последний зарезервированный блок всегда освобождается следующим.Это значительно упрощает отслеживание стека;освобождение блока из стека — это не что иное, как корректировка одного указателя.

Куча — это память, выделенная для динамического распределения.В отличие от стека, здесь нет принудительного шаблона выделения и освобождения блоков из кучи;вы можете выделить блок в любое время и освободить его в любое время.Это значительно усложняет отслеживание того, какие части кучи выделены или свободны в любой момент времени;Существует множество пользовательских распределителей кучи для настройки производительности кучи для различных шаблонов использования.

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

Чтобы ответить на ваши вопросы напрямую:

В какой степени они контролируются ОС или средой выполнения языка?

ОС выделяет стек для каждого потока системного уровня при его создании.Обычно операционная система вызывается средой выполнения языка для выделения кучи для приложения.

Какова их сфера применения?

Стек прикреплен к потоку, поэтому при выходе потока стек освобождается.Куча обычно выделяется средой выполнения при запуске приложения и освобождается при выходе из приложения (технического процесса).

Что определяет размер каждого из них?

Размер стека задается при создании потока.Размер кучи устанавливается при запуске приложения, но может увеличиваться по мере необходимости в пространстве (распределитель запрашивает больше памяти у операционной системы).

Что делает человека быстрее?

Стек работает быстрее, потому что шаблон доступа упрощает выделение и освобождение памяти из него (указатель/целое число просто увеличивается или уменьшается), в то время как в куче гораздо более сложный учет, связанный с выделением или освобождением.Кроме того, каждый байт в стеке имеет тенденцию очень часто повторно использоваться, что означает, что он имеет тенденцию отображаться в кэше процессора, что делает его очень быстрым.Еще одним недостатком производительности кучи является то, что куча, будучи в основном глобальным ресурсом, обычно должна быть многопоточной, т.е.каждое выделение и освобождение обычно должно быть синхронизировано со «всеми» другими доступами к куче в программе.

Наглядная демонстрация:
Источник изображения: vikashazrati.wordpress.com

Другие советы

Куча:

  • Хранится в оперативной памяти компьютера, как куча.
  • Переменные, созданные в стеке, выходят за пределы области действия и автоматически освобождаются.
  • Выделение происходит гораздо быстрее по сравнению с переменными в куче.
  • Реализовано с использованием реальной структуры данных стека.
  • Хранит локальные данные, адреса возврата, используемые для передачи параметров.
  • Может произойти переполнение стека, когда используется слишком большая часть стека (в основном из-за бесконечной или слишком глубокой рекурсии, очень больших выделений).
  • Данные, созданные в стеке, можно использовать без указателей.
  • Вы должны использовать стек, если точно знаете, сколько данных вам нужно выделить перед компиляцией, и он не слишком велик.
  • Обычно максимальный размер уже определен при запуске вашей программы.

Куча:

  • Хранится в оперативной памяти компьютера, как и стек.
  • В C++ переменные в куче должны уничтожаться вручную и никогда не выходить за пределы области видимости.Данные освобождаются с помощью delete, delete[], или free.
  • Медленнее выделение по сравнению с переменными в стеке.
  • Используется по требованию для выделения блока данных для использования программой.
  • Может иметь фрагментацию, когда имеется много выделений и освобождений.
  • В C++ или C данные, созданные в куче, будут указываться указателями и размещаться с помощью new или malloc соответственно.
  • Могут возникнуть сбои выделения, если запрошено выделение слишком большого буфера.
  • Вам следует использовать кучу, если вы не знаете точно, сколько данных вам понадобится во время выполнения, или если вам нужно выделить много данных.
  • Ответственен за утечки памяти.

Пример:

int foo()
{
  char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
  bool b = true; // Allocated on the stack.
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;

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

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

    Stack like a stack of papers

    Простота стека заключается в том, что вам не нужно вести таблицу, содержащую запись каждого раздела выделенной памяти;единственная информация о состоянии, которая вам нужна, — это один указатель на конец стека.Чтобы выделить и отменить выделение, вы просто увеличиваете и уменьшаете этот единственный указатель.Примечание:иногда можно реализовать стек, начинающийся с верхней части раздела памяти и расширяющийся вниз, а не вверх.

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

    Heap like a heap of licorice allsorts

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

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

  • В какой степени они контролируются ОС или средой выполнения языка?

    Как уже упоминалось, куча и стек — это общие термины, и их можно реализовать разными способами.Компьютерные программы обычно имеют стек, называемый стек вызовов который хранит информацию, относящуюся к текущей функции, такую ​​как указатель на ту функцию, из которой она была вызвана, и любые локальные переменные.Поскольку функции вызывают другие функции, а затем возвращаются, стек увеличивается и сжимается, чтобы хранить информацию от функций, находящихся дальше по стеку вызовов.Программа на самом деле не имеет контроля над ней во время выполнения;это определяется языком программирования, ОС и даже архитектурой системы.

    Куча — это общий термин, используемый для любой памяти, которая выделяется динамически и случайным образом;то естьвышел из строя.Память обычно выделяется операционной системой, а для этого приложение вызывает функции API.При управлении динамически выделяемой памятью требуется немало накладных расходов, которые обычно обрабатываются операционной системой.

  • Какова их сфера применения?

    Стек вызовов — это настолько низкоуровневая концепция, что он не имеет отношения к «области действия» в смысле программирования.Если вы дизассемблируете некоторый код, вы увидите ссылки в стиле относительных указателей на части стека, но что касается языка более высокого уровня, то язык налагает свои собственные правила области действия.Однако одним из важных аспектов стека является то, что как только функция возвращает значение, все локальное для этой функции немедленно освобождается из стека.Это работает так, как вы ожидаете, учитывая, как работают ваши языки программирования.В куче тоже сложно определиться.Областью действия является все, что предоставляется ОС, но ваш язык программирования, вероятно, добавляет свои правила относительно того, что такое «область действия» в вашем приложении.Архитектура процессора и ОС используют виртуальную адресацию, которую процессор транслирует в физические адреса и возникают страничные ошибки и т.д.Они отслеживают, какие страницы каким приложениям принадлежат.Однако вам никогда не придется беспокоиться об этом, потому что вы просто используете любой метод, который использует ваш язык программирования для выделения и освобождения памяти, и проверяете наличие ошибок (если выделение/освобождение не удается по какой-либо причине).

  • Что определяет размер каждого из них?

    Опять же, это зависит от языка, компилятора, операционной системы и архитектуры.Стек обычно выделяется заранее, поскольку по определению это должна быть непрерывная память (подробнее об этом в последнем абзаце).Компилятор языка или операционная система определяют его размер.Вы не храните в стеке огромные объемы данных, поэтому он будет достаточно большим, чтобы его никогда не приходилось использовать полностью, за исключением случаев нежелательной бесконечной рекурсии (следовательно, «переполнения стека») или других необычных программных решений.

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

  • Что делает человека быстрее?

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

(Я переместил этот ответ из другого вопроса, который был более или менее обманом этого вопроса.)

Ответ на ваш вопрос зависит от реализации и может различаться в зависимости от компилятора и архитектуры процессора.Однако вот упрощенное объяснение.

  • И стек, и куча представляют собой области памяти, выделенные базовой операционной системой (часто виртуальная память, которая по требованию отображается в физическую память).
  • В многопоточной среде каждый поток будет иметь свой полностью независимый стек, но они будут совместно использовать кучу.Параллельный доступ должен контролироваться в куче и невозможен в стеке.

Куча

  • Куча содержит связанный список использованных и свободных блоков.Новые распределения в куче (по new или malloc) удовлетворяются созданием подходящего блока из одного из свободных блоков.Это требует обновления списка блоков в куче.Этот метаинформация Информация о блоках в куче также хранится в куче, часто на небольшой площади прямо перед каждым блоком.
  • По мере роста кучи новые блоки часто распределяются от младших адресов к более высоким.Таким образом, вы можете думать о куче как о куча блоков памяти, размер которых увеличивается по мере выделения памяти.Если куча слишком мала для выделения, ее размер часто можно увеличить, получив больше памяти от базовой операционной системы.
  • Выделение и освобождение множества маленьких блоков может привести к тому, что куча окажется в состоянии, когда между использованными блоками разбросано множество маленьких свободных блоков.Запрос на выделение большого блока может завершиться неудачей, поскольку ни один из свободных блоков не является достаточно большим, чтобы удовлетворить запрос на выделение, даже если общий размер свободных блоков может быть достаточно большим.Это называется фрагментация кучи.
  • Когда используемый блок, соседний со свободным блоком, освобождается, новый свободный блок может быть объединен с соседним свободным блоком для создания более крупного свободного блока, эффективно уменьшающего фрагментацию кучи.

The heap

Стек

  • Стек часто работает в тесном тандеме со специальным регистром ЦП, называемым указатель стека.Первоначально указатель стека указывает на вершину стека (самый высокий адрес в стеке).
  • ЦП имеет специальные инструкции для толкая значения в стек и выскакивают их обратно из стека.Каждый толкать сохраняет значение в текущем местоположении указателя стека и уменьшает указатель стека.А поп извлекает значение, на которое указывает указатель стека, а затем увеличивает указатель стека (не смущайтесь тем фактом, что добавление значение в стеке уменьшается указатель стека и удаление ценность увеличивается это.Помните, что стек растет вниз).Сохраняемые и извлекаемые значения являются значениями регистров ЦП.
  • При вызове функции ЦП использует специальные инструкции, которые передают текущую указатель инструкций, т.е.адрес кода, выполняющегося в стеке.Затем процессор прыгает на функцию, установив указатель инструкции на адрес вызываемой функции.Позже, когда функция завершает работу, старый указатель инструкции извлекается из стека, и выполнение возобновляется с кода сразу после вызова функции.
  • При вводе функции указатель стека уменьшается, чтобы выделить больше места в стеке для локальных (автоматических) переменных.Если функция имеет одну локальную 32-битную переменную, в стеке резервируются четыре байта.Когда функция завершает работу, указатель стека перемещается назад, чтобы освободить выделенную область.
  • Если у функции есть параметры, они помещаются в стек перед вызовом функции.Затем код функции может перемещаться вверх по стеку от текущего указателя стека, чтобы найти эти значения.
  • Вызовы вложенных функций работают как шарм.При каждом новом вызове будут выделяться параметры функции, адрес возврата и пространство для локальных переменных. записи активации может складываться для вложенных вызовов и корректно разворачиваться при возврате функций.
  • Поскольку стек представляет собой ограниченный блок памяти, вы можете вызвать переполнение стека вызывая слишком много вложенных функций и/или выделяя слишком много места для локальных переменных.Часто область памяти, используемая для стека, настроена таким образом, что запись ниже нижнего (самого низкого адреса) стека вызовет ловушку или исключение в ЦП.Это исключительное состояние затем может быть обнаружено средой выполнения и преобразовано в своего рода исключение переполнения стека.

The stack

Можно ли разместить функцию в куче, а не в стеке?

Нет, записи активации для функций (т.е.локальные или автоматические переменные) выделяются в стеке, который используется не только для хранения этих переменных, но и для отслеживания вызовов вложенных функций.

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

Однако стек — это функция более низкого уровня, тесно связанная с архитектурой процессора.Увеличение кучи, когда недостаточно места, не так уж и сложно, поскольку это можно реализовать в вызове библиотеки, обрабатывающей кучу.Однако увеличение стека часто невозможно, поскольку переполнение стека обнаруживается только тогда, когда уже слишком поздно;и закрытие потока выполнения является единственным жизнеспособным вариантом.

В следующем коде C#

public void Method1()
{
    int i = 4;
    int y = 2;
    class1 cls1 = new class1();
}

Вот как управляется память

Picture of variables on the stack

Local Variables это должно длиться только до тех пор, пока вызов функции находится в стеке.Куча используется для переменных, время жизни которых мы заранее не знаем, но ожидаем, что они продлятся некоторое время.В большинстве языков очень важно во время компиляции знать, насколько велика переменная, если мы хотим сохранить ее в стеке.

Объекты (размер которых меняется по мере их обновления) помещаются в кучу, потому что во время создания мы не знаем, как долго они будут существовать.Во многих языках куча представляет собой сбор мусора для поиска объектов (таких как объект cls1), которые больше не имеют ссылок.

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

Более подробную информацию можно найти здесь:

Разница между распределением памяти в стеке и куче « timmurphy.org

и здесь:

Создание объектов в стеке и куче

Эта статья является источником изображения выше: Шесть важных концепций .NET:Стек, куча, типы значений, ссылочные типы, упаковка и распаковка — CodeProject

но имейте в виду, что он может содержать некоторые неточности.

СтекКогда вы вызываете функцию, аргументы этой функции плюс некоторые другие накладные расходы помещаются в стек.Некоторая информация (например, куда идти по возвращении) также хранится там.Когда вы объявляете переменную внутри своей функции, эта переменная также выделяется в стеке.

Освободить стек довольно просто, потому что вы всегда освобождаете стек в порядке, обратном тому, в котором вы выделяли.Содержимое стека добавляется при входе в функции, соответствующие данные удаляются при выходе из них.Это означает, что вы склонны оставаться в пределах небольшой области стека, если только вы не вызываете множество функций, которые вызывают множество других функций (или не создаете рекурсивное решение).

КучаКуча — это общее название места, куда помещаются данные, создаваемые на лету.Если вы не знаете, сколько космических кораблей собирается создать ваша программа, вы, скорее всего, будете использовать оператор new (или malloc или его эквивалент) для создания каждого космического корабля.Это распределение будет сохраняться какое-то время, поэтому, скорее всего, мы будем освобождать вещи в другом порядке, чем мы их создали.

Таким образом, куча гораздо сложнее, потому что в конечном итоге существуют неиспользуемые области памяти, чередующиеся с частями, которые - память фрагментируется.Найти свободную память нужного вам размера – непростая задача.Вот почему следует избегать кучи (хотя она все еще часто используется).

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

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

Физическое расположение в памятиЭто менее актуально, чем вы думаете, из-за технологии под названием Виртуальная память что заставляет вашу программу думать, что у вас есть доступ к определенному адресу, где физические данные находятся где-то еще (даже на жестком диске!).Адреса, которые вы получаете для стека, располагаются в порядке возрастания по мере того, как ваше дерево вызовов становится глубже.Адреса кучи непредсказуемы (т.е. зависят от реализации) и, честно говоря, не важны.

Чтобы уточнить, этот ответ есть неверная информация(Томас исправил свой ответ после комментариев, круто :) ).Другие ответы просто избегают объяснения того, что означает статическое распределение.Поэтому ниже я объясню три основные формы распределения и то, как они обычно связаны с кучей, стеком и сегментом данных.Я также покажу несколько примеров на C/C++ и Python, чтобы помочь людям понять.

«Статические» (статически выделенные) переменные не размещаются в стеке.Не думайте так — многие люди так поступают только потому, что «статический» очень похож на «стек».На самом деле они не существуют ни в стеке, ни в куче.Они являются частью того, что называется сегмент данных.

Однако, как правило, лучше учитывать "объем" и "продолжительность жизни", а не "стек" и "куча".

Область действия определяет, какие части кода могут иметь доступ к переменной.Обычно мы думаем о локальная область действия (доступен только текущей функции) по сравнению с глобальная область действия (доступен где угодно), хотя область действия может быть намного сложнее.

Время жизни относится к тому моменту, когда переменная выделяется и освобождается во время выполнения программы.Обычно мы думаем о статическое размещение (переменная будет сохраняться на протяжении всей программы, что делает ее полезной для хранения одной и той же информации при нескольких вызовах функций) по сравнению с автоматическое распределение (переменная сохраняется только во время одного вызова функции, что делает ее полезной для хранения информации, которая используется только во время вашей функции и может быть удалена после завершения) по сравнению с динамическое размещение (переменные, продолжительность которых определяется во время выполнения, а не во время компиляции, как статическая или автоматическая).

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

Я приведу простой аннотированный код C, чтобы проиллюстрировать все это.Лучший способ научиться — запустить программу под отладчиком и наблюдать за ее поведением.Если вы предпочитаете читать Python, перейдите к концу ответа :)

// Statically allocated in the data segment when the program/DLL is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in the code
int someGlobalVariable;

// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in this particular code file
static int someStaticVariable;

// "someArgument" is allocated on the stack each time MyFunction is called
// "someArgument" is deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
void MyFunction(int someArgument) {

    // Statically allocated in the data segment when the program is first loaded
    // Deallocated when the program/DLL exits
    // scope - can be accessed only within MyFunction()
    static int someLocalStaticVariable;

    // Allocated on the stack each time MyFunction is called
    // Deallocated when MyFunction returns
    // scope - can be accessed only within MyFunction()
    int someLocalVariable;

    // A *pointer* is allocated on the stack each time MyFunction is called
    // This pointer is deallocated when MyFunction returns
    // scope - the pointer can be accessed only within MyFunction()
    int* someDynamicVariable;

    // This line causes space for an integer to be allocated in the heap
    // when this line is executed. Note this is not at the beginning of
    // the call to MyFunction(), like the automatic variables
    // scope - only code within MyFunction() can access this space
    // *through this particular variable*.
    // However, if you pass the address somewhere else, that code
    // can access it too
    someDynamicVariable = new int;


    // This line deallocates the space for the integer in the heap.
    // If we did not write it, the memory would be "leaked".
    // Note a fundamental difference between the stack and heap
    // the heap must be managed. The stack is managed for us.
    delete someDynamicVariable;

    // In other cases, instead of deallocating this heap space you
    // might store the address somewhere more permanent to use later.
    // Some languages even take care of deallocation for you... but
    // always it needs to be taken care of at runtime by some mechanism.

    // When the function returns, someArgument, someLocalVariable
    // and the pointer someDynamicVariable are deallocated.
    // The space pointed to by someDynamicVariable was already
    // deallocated prior to returning.
    return;
}

// Note that someGlobalVariable, someStaticVariable and
// someLocalStaticVariable continue to exist, and are not
// deallocated until the program exits.

Особенно ярким примером того, почему важно различать время жизни и область действия, является то, что переменная может иметь локальную область действия, но статическое время жизни — например, «someLocalStaticVariable» в приведенном выше примере кода.Такие переменные могут сделать наши общие, но неформальные привычки именования очень запутанными.Например, когда мы говорим: «местный"мы обычно имеем в виду"автоматически выделяемая переменная локальной области действия"и когда мы говорим глобальные, мы обычно имеем в виду "статически выделенная переменная глобальной области видимости".К сожалению, когда дело доходит до таких вещей, как «статически выделенные переменные в области файла"Многие люди просто говорят..."хм???".

Некоторые варианты синтаксиса в C/C++ усугубляют эту проблему — например, многие люди думают, что глобальные переменные не являются «статическими» из-за синтаксиса, показанного ниже.

int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation

int main() {return 0;}

Обратите внимание, что добавление ключевого слова «static» в приведенное выше объявление не позволяет var2 иметь глобальную область видимости.Тем не менее, глобальная переменная var1 имеет статическое распределение.Это не интуитивно!По этой причине я стараюсь никогда не использовать слово «статический» при описании области действия, а вместо этого говорю что-то вроде «файловая» или «ограниченная файлом» область.Однако многие люди используют фразу «статический» или «статическая область действия» для описания переменной, доступ к которой возможен только из одного файла кода.В контексте жизни «статика» всегда означает, что переменная выделяется при запуске программы и освобождается при выходе из программы.

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

from datetime import datetime

class Animal:
    _FavoriteFood = 'Undefined' # _FavoriteFood is statically allocated

    def PetAnimal(self):
        curTime = datetime.time(datetime.now()) # curTime is automatically allocatedion
        print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)

class Cat(Animal):
    _FavoriteFood = 'tuna' # Note since we override, Cat class has its own statically allocated _FavoriteFood variable, different from Animal's

class Dog(Animal):
    _FavoriteFood = 'steak' # Likewise, the Dog class gets its own static variable. Important to note - this one static variable is shared among all instances of Dog, hence it is not dynamic!


if __name__ == "__main__":
    whiskers = Cat() # Dynamically allocated
    fido = Dog() # Dynamically allocated
    rinTinTin = Dog() # Dynamically allocated

    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

    Dog._FavoriteFood = 'milkbones'
    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

# Output is:
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is milkbones
# Thank you for petting me. But it's 13:05:02.256000, you should feed me. My favorite food is milkbones

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

  1. Стек и куча не обязательно должны быть единичными.Распространенной ситуацией, когда у вас есть более одного стека, является наличие более одного потока в процессе.В этом случае каждый поток имеет свой стек.Вы также можете иметь более одной кучи, например, некоторые конфигурации DLL могут привести к выделению разных DLL из разных куч, поэтому обычно освобождать память, выделенную другой библиотекой, — плохая идея.

  2. В C вы можете получить выгоду от выделения переменной длины, используя аллока, который выделяет в стеке, в отличие от alloc, который выделяет в куче.Эта память не выдержит ваш оператор возврата, но она полезна для временного буфера.

  3. Создание огромного временного буфера в Windows, которым вы мало пользуетесь, не является бесплатным.Это связано с тем, что компилятор генерирует цикл проверки стека, который вызывается каждый раз при входе в вашу функцию, чтобы убедиться, что стек существует (поскольку Windows использует одну защитную страницу в конце вашего стека, чтобы определить, когда необходимо увеличить стек.Если вы получите доступ к памяти более чем на одну страницу от конца стека, произойдет сбой).Пример:

void myfunction()
{
   char big[10000000];
   // Do something that only uses for first 1K of big 99% of the time.
}

Другие прямо ответили на ваш вопрос, но, пытаясь понять стек и кучу, я думаю, полезно рассмотреть структуру памяти традиционного процесса UNIX (без потоков и mmap()-основанные распределители).А Глоссарий по управлению памятью на веб-странице есть схема этого расположения памяти.

Стек и куча традиционно расположены на противоположных концах виртуального адресного пространства процесса.Стек автоматически увеличивается при доступе к размеру, установленному ядром (который можно настроить с помощью setrlimit(RLIMIT_STACK, ...)).Куча увеличивается, когда распределитель памяти вызывает brk() или sbrk() системный вызов, отображающий больше страниц физической памяти в виртуальное адресное пространство процесса.

В системах без виртуальной памяти, таких как некоторые встроенные системы, часто применяется та же базовая схема, за исключением того, что размер стека и кучи фиксирован.Однако в других встроенных системах (например, на базе микроконтроллеров Microchip PIC) программный стек представляет собой отдельный блок памяти, который не адресуется инструкциями перемещения данных и может быть изменен или прочитан только косвенно через инструкции потока программы (вызов, возврат и др.).Другие архитектуры, например процессоры Intel Itanium, имеют несколько стеков.В этом смысле стек является элементом архитектуры ЦП.

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

Куча — это часть памяти, которая предоставляется приложению операционной системой, обычно через системный вызов, такой как malloc.В современных ОС эта память представляет собой набор страниц, доступ к которым имеет только вызывающий процесс.

Размер стека определяется во время выполнения программы и обычно не увеличивается после запуска программы.В программе на языке C стек должен быть достаточно большим, чтобы вместить каждую переменную, объявленную внутри каждой функции.Куча будет расти динамически по мере необходимости, но в конечном итоге вызов делает операционная система (часто она увеличивает кучу больше, чем значение, запрошенное malloc, так что, по крайней мере, некоторым будущим функциям malloc не придется возвращаться в ядро ​​для получить больше памяти.Такое поведение часто настраивается)

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

Я думаю, что многие другие люди дали вам в основном правильные ответы по этому вопросу.

Однако одна деталь, которая была упущена, заключается в том, что «кучу», вероятно, следует называть «свободным хранилищем».Причиной этого различия является то, что оригинальный свободный магазин был реализован со структурой данных, известной как «биномиальная куча». По этой причине выделение с ранних реализаций Malloc ()/Free () было выделено из кучи.Однако в наши дни большинство бесплатных хранилищ реализованы с очень сложными структурами данных, которые не являются биномиальными кучами.

Что такое стек?

Стопка — это стопка объектов, обычно аккуратно расположенных.

Enter image description here

Стеки в вычислительных архитектурах — это области памяти, в которых данные добавляются или удаляются по принципу «последним пришел — первым вышел».
В многопоточном приложении каждый поток будет иметь свой стек.

Что такое куча?

Куча – это беспорядочная совокупность вещей, сложенных вразброс.

Enter image description here

В вычислительных архитектурах куча — это область динамически выделяемой памяти, которая автоматически управляется операционной системой или библиотекой диспетчера памяти.
Память в куче регулярно выделяется, освобождается и изменяется во время выполнения программы, и это может привести к проблеме, называемой фрагментацией.
Фрагментация возникает, когда объекты памяти выделяются с небольшими промежутками между ними, которые слишком малы для размещения дополнительных объектов памяти.
Конечным результатом является процент пространства кучи, который невозможно использовать для дальнейшего распределения памяти.

Оба вместе

В многопоточном приложении каждый поток будет иметь свой стек.Но все разные потоки будут совместно использовать кучу.
Поскольку разные потоки совместно используют кучу в многопоточном приложении, это также означает, что между потоками должна быть некоторая координация, чтобы они не пытались получить доступ и манипулировать одним и тем же фрагментом(ами) памяти в куче. в то же время.

Что быстрее — стек или куча?И почему?

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

Для людей, плохо знакомых с программированием, вероятно, будет хорошей идеей использовать стек, поскольку это проще.
Поскольку стек невелик, его следует использовать, если вы точно знаете, сколько памяти понадобится для ваших данных, или если вы знаете, что размер ваших данных очень мал.
Лучше использовать кучу, когда вы знаете, что вам понадобится много памяти для ваших данных, или вы просто не уверены, сколько памяти вам понадобится (как в случае с динамическим массивом).

Модель памяти Java

Enter image description here

Стек — это область памяти, где хранятся локальные переменные (включая параметры метода).Когда дело доходит до объектных переменных, это просто ссылки (указатели) на реальные объекты в куче.
Каждый раз, когда создается экземпляр объекта, часть кучи памяти выделяется для хранения данных (состояния) этого объекта.Поскольку объекты могут содержать другие объекты, некоторые из этих данных могут фактически содержать ссылки на эти вложенные объекты.

Со стеком можно делать некоторые интересные вещи.Например, у вас есть такие функции, как аллока (при условии, что вы сможете обойти многочисленные предупреждения относительно его использования), который представляет собой форму malloc, которая специально использует для памяти стек, а не кучу.

Тем не менее, ошибки памяти на основе стека — одни из худших, с которыми я когда-либо сталкивался.Если вы используете динамическую память и выходите за пределы выделенного блока, у вас есть хороший шанс вызвать ошибку сегмента.(Не 100%:ваш блок может быть случайно смежным с другим, который вы ранее выделили.) Но поскольку переменные, созданные в стеке, всегда смежны друг с другом, запись за пределы может изменить значение другой переменной.Я понял, что всякий раз, когда я чувствую, что моя программа перестает подчиняться законам логики, это, вероятно, переполнение буфера.

Проще говоря, стек — это место, где создаются локальные переменные.Кроме того, каждый раз, когда вы вызываете подпрограмму, счетчик программы (указатель на следующую машинную инструкцию) и все важные регистры, а иногда и параметры помещаются в стек.Затем любые локальные переменные внутри подпрограммы помещаются в стек (и используются оттуда).Когда подпрограмма завершается, все это извлекается обратно из стека.Данные ПК и регистров возвращаются туда, где они были при загрузке, так что ваша программа может продолжать свой путь.

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

В «классических» системах ОЗУ располагалось так, что указатель стека начинался снизу памяти, указатель кучи начинался сверху, и они росли навстречу друг другу.Если они перекрываются, у вас недостаточно оперативной памяти.Однако это не работает с современными многопоточными ОС.Каждый поток должен иметь свой собственный стек, и его можно создавать динамически.

Из WikiAnwser.

Куча

Когда функция или метод вызывает другую функцию, которая, в свою очередь, вызывает другую функцию и т. д., выполнение всех этих функций приостанавливается до тех пор, пока самая последняя функция не вернет свое значение.

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

Стек важно учитывать при обработке исключений и выполнении потоков.

Куча

Куча — это просто память, используемая программами для хранения переменных.Элементы кучи (переменные) не имеют зависимостей друг от друга и всегда доступны случайным образом в любое время.

Куча

  • Очень быстрый доступ
  • Не нужно явно освобождать переменные
  • Пространство эффективно управляется процессором, память не фрагментируется.
  • Только локальные переменные
  • Ограничение на размер стека (зависит от ОС)
  • Размер переменных нельзя изменить

Куча

  • Доступ к переменным возможен глобально.
  • Нет ограничений на размер памяти
  • (Относительно) более медленный доступ
  • Нет гарантированного эффективного использования пространства, память может со временем фрагментироваться, поскольку блоки памяти выделяются, а затем освобождаются.
  • Вы должны управлять памятью (вы отвечаете за выделение и освобождение переменных)
  • Размер переменных можно изменить с помощью функции realloc().

ХОРОШО, просто и короткими словами они означают заказал и не заказано...!

Куча:В стеке элементы располагаются друг над другом, а это значит, что обработка будет быстрее и эффективнее!...

Таким образом, всегда есть индекс, указывающий на конкретный элемент, а также обработка будет быстрее, а также существует связь между элементами!...

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

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

enter image description here

Суммируя

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


В деталях

Стек

Стек представляет собой структуру данных «LIFO» (последний вошел — первый вышел), которая довольно тщательно управляется и оптимизируется процессором.Каждый раз, когда функция объявляет новую переменную, она «помещается» в стек.Затем каждый раз, когда функция завершает работу, все переменные, помещенные этой функцией в стек, освобождаются (то есть удаляются).Как только переменная стека освобождается, эта область памяти становится доступной для других переменных стека.

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

Больше можно найти здесь.


Куча

Куча — это область памяти вашего компьютера, которая не управляется автоматически и не так строго контролируется процессором.Это более свободная область памяти (и она больше).Чтобы выделить память в куче, вы должны использовать malloc() или calloc(), которые являются встроенными функциями C.После того как вы выделили память в куче, вы несете ответственность за использование функции free() для освобождения этой памяти, когда она вам больше не понадобится.

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

В отличие от стека, куча не имеет ограничений по размеру переменных (кроме очевидных физических ограничений вашего компьютера).Чтение и запись в куче немного медленнее, поскольку для доступа к памяти в куче приходится использовать указатели.Вскоре мы поговорим об указателях.

В отличие от стека, переменные, созданные в куче, доступны любой функции в любом месте вашей программы.Переменные кучи по сути являются глобальными по своей области действия.

Больше можно найти здесь.


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

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

Enter image description here

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

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

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

Enter image description here

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

Даже более подробно описано здесь и здесь.


Теперь подойдите к ответы на ваш вопрос.

В какой степени они контролируются ОС или средой выполнения языка?

ОС выделяет стек для каждого потока системного уровня при его создании.Обычно операционная система вызывается средой выполнения языка для выделения кучи для приложения.

Больше можно найти здесь.

Какова их сфера применения?

Уже дано в топе.

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

Больше можно найти в здесь.

Что определяет размер каждого из них?

Размер стека задается Операционные системы когда создается поток.Размер кучи устанавливается при запуске приложения, но он может увеличиваться по мере необходимости в пространстве (распределитель запрашивает больше памяти у операционной системы).

Что делает человека быстрее?

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

Кроме того, стек против.куча — это не только фактор производительности;это также многое говорит вам об ожидаемом времени жизни объектов.

Подробности можно узнать из здесь.

В 1980-е годы UNIX распространялась как кролики, а крупные компании создавали свои собственные системы.У Exxon была такая компания, как и у десятков торговых марок, затерянных в истории.Расположение памяти оставалось на усмотрение многих разработчиков.

Типичная программа C была изложена в памяти с возможностью увеличения путем изменения значения BRK ().Как правило, куча была чуть ниже этого значения BRK, и увеличение BRK увеличило количество доступной кучи.

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

Одним из типичных блоков памяти был BSS (блок нулевого значения), который случайно не был обнулян в предложении одного производителя.Другой — DATA, содержащий инициализированные значения, включая строки и числа.Третьим был CODE, содержащий CRT (среда выполнения C), основную часть, функции и библиотеки.

Появление виртуальной памяти в UNIX меняет многие ограничения.Нет никакой объективной причины, по которой эти блоки должны быть смежными или фиксированными по размеру или упорядочены конкретным способом сейчас.Конечно, до UNIX была Multics, которая не страдала от этих ограничений.Вот схема, показывающая одну из схем памяти той эпохи.

A typical 1980s style UNIX C program memory layout

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

stack, heap and static data

Пара центов:Думаю, хорошо будет нарисовать память графически и попроще:

This is my vision of process memory construction with simplification for more easy understanding wht happening


Стрелки — показывают, где растет стек и куча, размер стека процесса имеет ограничение, определенное в ОС, ограничения размера стека потоков обычно определяются параметрами в API создания потока.Куча обычно ограничивается максимальным размером виртуальной памяти процесса, например для 32-разрядной версии 2–4 ГБ.

Такой простой способ:Куча процесса является общей для процесса и всех потоков внутри, обычно используется для распределения памяти с чем-то вроде маллок().

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

Поскольку некоторые ответы оказались придирчивыми, я внесу свою лепту.

Удивительно, но никто не упомянул об этом кратном (т.не связано с количеством запущенных потоков на уровне ОС) стеки вызовов встречаются не только в экзотических языках (PostScript) или платформах (Intel Itanium), но и в волокна, зеленые нитки и некоторые реализации сопрограммы.

Файберы, зеленые потоки и сопрограммы во многом схожи, что приводит к большой путанице.Разница между волокнами и зелеными потоками заключается в том, что первые используют кооперативную многозадачность, а вторые могут иметь как кооперативную, так и вытесняющую (или даже и то, и другое).О различии между волокнами и сопрограммами см. здесь.

В любом случае, цель как волокон, так и зеленых потоков и сопрограмм заключается в одновременном выполнении нескольких функций, но нет параллельно (см. это ТАК вопрос для различия) в пределах одного потока уровня ОС, организованно передавая управление друг от друга туда и обратно.

При использовании волокон, зеленых нитей или сопрограмм вы обычно иметь отдельный стек для каждой функции.(Технически не только стек, но и целый контекст выполнения относится к каждой функции.Самое главное, регистры ЦП.) Для каждого потока существует столько стеков, сколько одновременно выполняется функций, и поток переключается между выполнением каждой функции в соответствии с логикой вашей программы.Когда функция доходит до конца, ее стек уничтожается.Так, количество и время жизни стеков динамичны и не определяются количеством потоков уровня ОС!

Заметьте, я сказал: «обычно иметь отдельный стек для каждой функции».есть оба стопкой и без штабеля реализации курутин.Наиболее известными стековыми реализациями C++ являются Boost.Coroutine и Microsoft PPL's async/await.(Однако C++ возобновляемые функции (он же"async и await"), которые были предложены в C++17, скорее всего, будут использовать сопрограммы без стека.)

Скоро появится предложение Fibers для стандартной библиотеки C++.Также есть сторонние библиотеки.Зеленые потоки чрезвычайно популярны в таких языках, как Python и Ruby.

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

Куча

  • Очень быстрый доступ.
  • Хранится в оперативной памяти.
  • Здесь загружаются вызовы функций вместе с переданными локальными переменными и параметрами функции.
  • Пространство освобождается автоматически, когда программа выходит за пределы области действия.
  • Хранится в последовательной памяти.

Куча

  • Медленный доступ по сравнению со Stack.
  • Хранится в оперативной памяти.
  • Здесь хранятся динамически созданные переменные, которые в дальнейшем требуют освобождения выделенной памяти после использования.
  • Хранится везде, где выполняется выделение памяти, всегда доступен по указателю.

Интересное замечание:

  • Если бы вызовы функций хранились в куче, это привело бы к двум неприятным моментам:
    1. Благодаря последовательному хранению в стеке выполнение выполняется быстрее.Хранение в куче привело бы к огромным затратам времени, что замедлило бы выполнение всей программы.
    2. Если бы функции хранились в куче (беспорядочное хранилище, на которое указывает указатель), не было бы возможности вернуться обратно к адресу вызывающей стороны (что дает стек из-за последовательного хранения в памяти).

Многие ответы верны как концепции, но мы должны отметить, что стек необходим аппаратному обеспечению (т.е.микропроцессор), чтобы разрешить вызов подпрограмм (CALL на языке ассемблера..).(ООП ребята назовут это методы)

В стеке вы сохраняете адреса возврата и вызов → push/ret → pop управляется непосредственно аппаратно.

Вы можете использовать стек для передачи параметров.даже если это медленнее, чем использование регистров (скажет ли гуру микропроцессоров или хорошая книга по BIOS 1980-х годов...)

  • Без стека нет микропроцессор может работать.(мы не можем представить программу, даже на ассемблере, без подпрограмм/функций)
  • Без кучи можно.(Программа на языке ассемблера может работать без него, поскольку куча — это концепция ОС, а malloc — это вызов OS/Lib.

Использование стека происходит быстрее, поскольку:

  • Это аппаратное обеспечение, и даже push/pop очень эффективны.
  • malloc требует входа в режим ядра, использования блокировки/семафора (или других примитивов синхронизации), выполнения некоторого кода и управления некоторыми структурами, необходимыми для отслеживания распределения.

Ух ты!Так много ответов, и я не думаю, что один из них понял правильно...

1) Где и какие они находятся (физически в памяти реального компьютера)?

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

Есть две кучи:общественное и частное.

Частная куча начинается на границе 16 байт (для 64-битных программ) или на границе 8 байт (для 32-битных программ) после последнего байта кода в вашей программе, а затем увеличивается в значении.Ее также называют кучей по умолчанию.

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

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

2) В какой степени они контролируются ОС или средой выполнения языка?

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

2б) Какова их сфера применения?

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

2в) Чем определяется размер каждого из них?

Размер стека и частной кучи определяется параметрами времени выполнения вашего компилятора.Публичная куча инициализируется во время выполнения с использованием параметра размера.

2d) Что делает человека быстрее?

Они созданы не для того, чтобы быть быстрыми, а для того, чтобы быть полезными.То, как программист их использует, определяет, будут ли они «быстрыми» или «медленными».

ССЫЛКА:

https://norasandler.com/2019/02/18/Write-a-Compiler-10.html

https://docs.microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-getprocessheap

https://docs.microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-heapcreate

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top