Короче говоря
Стек используется для статического выделения памяти и куча для динамического выделения памяти, которые хранятся в оперативной памяти компьютера.
В деталях
Стек
Стек представляет собой структуру данных «LIFO» (последний пришел, первый вышел), которая управляется и оптимизируется центральным процессором довольно близко. Каждый раз, когда функция объявляет новую переменную, она «помещается» в стек. Затем каждый раз при выходе из функции все переменные, помещаемые в стек этой функцией, освобождаются (то есть они удаляются). После освобождения переменной стека эта область памяти становится доступной для других переменных стека.
Преимущество использования стека для хранения переменных заключается в том, что память управляется за вас. Вам не нужно выделять память вручную или освобождать ее, если она вам больше не нужна. Более того, поскольку процессор эффективно организует стековую память, чтение и запись в переменные стека происходит очень быстро.
Больше можно найти здесь .
Куча
Куча - это область памяти вашего компьютера, которая не управляется автоматически и не так жестко управляется процессором. Это более свободно плавающая область памяти (и больше). Чтобы выделить память в куче, вы должны использовать malloc () или calloc (), которые являются встроенными функциями C. После выделения памяти в куче вы несете ответственность за использование free () для освобождения этой памяти, когда она вам больше не нужна.
Если вы этого не сделаете, ваша программа будет иметь то, что известно как утечка памяти. То есть память в куче все равно будет выделена (и не будет доступна другим процессам). Как мы увидим в разделе отладки, есть инструмент под названием Valgrind, который может помочь вам обнаружить утечки памяти.
В отличие от стека, куча не имеет ограничений по размеру переменного размера (кроме очевидных физических ограничений вашего компьютера). Память кучи немного медленнее для чтения и записи, потому что для доступа к памяти в куче нужно использовать указатели. Мы поговорим об указателях в ближайшее время.
В отличие от стека, переменные, созданные в куче, доступны любой функции в любой точке вашей программы. Переменные кучи по сути являются глобальными.
Больше можно найти здесь .
Переменные, размещенные в стеке, сохраняются непосредственно в памяти, и доступ к этой памяти очень быстрый, и его распределение решается при компиляции программы. Когда функция или метод вызывает другую функцию, которая, в свою очередь, вызывает другую функцию и т. Д., Выполнение всех этих функций приостанавливается до тех пор, пока самая последняя функция не вернет свое значение. Стек всегда резервируется в порядке LIFO, последний зарезервированный блок всегда является следующим блоком, который должен быть освобожден. Это действительно упрощает отслеживание стека, освобождение блока из стека - всего лишь настройка одного указателя.
Переменным, выделенным в куче, выделяется память во время выполнения, и доступ к этой памяти немного медленнее, но размер кучи ограничен только размером виртуальной памяти. Элементы кучи не имеют зависимостей друг от друга и всегда могут быть доступны случайным образом в любое время. Вы можете выделить блок в любое время и освободить его в любое время. Это значительно усложняет отслеживание того, какие части кучи выделены или свободны в любой момент времени.
Вы можете использовать стек, если точно знаете, сколько данных вам нужно выделить до компиляции, и он не слишком велик. Вы можете использовать кучу, если вы точно не знаете, сколько данных вам потребуется во время выполнения или если вам нужно выделить много данных.
В многопоточной ситуации каждый поток будет иметь свой собственный полностью независимый стек, но они будут совместно использовать кучу. Стек зависит от потока, а куча зависит от приложения. Стек важно учитывать при обработке исключений и выполнении потоков.
Каждый поток получает стек, в то время как для приложения обычно есть только одна куча (хотя весьма часто иметь несколько куч для разных типов размещения).
Во время выполнения, если приложению требуется больше кучи, оно может выделить память из свободной памяти, а если стеку требуется память, оно может выделить память из свободной памяти, выделенной для приложения.
Даже более подробно здесь и здесь .
Теперь перейдите к ответам на ваш вопрос .
В какой степени они контролируются ОС или языковой средой выполнения?
ОС выделяет стек для каждого потока системного уровня при его создании. Обычно ОС вызывается языковой средой выполнения для выделения кучи для приложения.
Больше можно найти здесь .
Какова их сфера применения?
Уже дано в топе.
«Вы можете использовать стек, если точно знаете, сколько данных нужно выделить до компиляции, и он не слишком большой. Вы можете использовать кучу, если точно не знаете, сколько данных вам потребуется во время выполнения или если вам нужно выделить много данных. "
Больше можно найти здесь .
От чего зависит размер каждого из них?
Размер стека устанавливается ОС при создании потока. Размер кучи устанавливается при запуске приложения, но может увеличиваться по мере необходимости в пространстве (распределитель запрашивает больше памяти у операционной системы).
Что делает быстрее?
Распределение стека происходит намного быстрее, поскольку все, что он на самом деле делает - это перемещает указатель стека. Используя пулы памяти, вы можете получить сопоставимую производительность за счет распределения кучи, но это связано с небольшой дополнительной сложностью и собственными головными болями.
Кроме того, стек против кучи - это не только вопрос производительности; он также много говорит вам об ожидаемом времени жизни объектов.
Подробности можно найти здесь .