В чем разница между стеком (stack) и кучей (heap) в управлении памятью?

Ответ

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

Аспект Стек (Stack) Куча (Heap)
Управление Автоматическое (LIFO). Компилятор выделяет/освобождает память при входе/выходе из области видимости (функции). Ручное или через сборщик мусора (GC/ARC). Программист запрашивает выделение (malloc, new) и отвечает за освобождение (free, delete).
Скорость Очень высокая. Выделение — простое перемещение указателя стека. Относительно медленная. Требуется поиск свободного блока и синхронизация в многопоточных средах.
Размер Ограничен (обычно несколько МБ). Переполнение приводит к crash (Stack Overflow). Большой, ограничен объемом всей доступной ОЗУ.
Типы данных Локальные переменные, аргументы функций, указатели на объекты в куче. Динамически создаваемые объекты, большие массивы данных, всё, что должно жить дольше вызова функции.
Фрагментация Отсутствует. Возможна, требует дефрагментации.

Пример на C:

void example() {
    int onStack = 42; // Переменная в стеке
    int *onHeap = (int*)malloc(sizeof(int)); // Память выделена в куче
    *onHeap = 100;
    free(onHeap); // Обязательно освободить!
} // 'onStack' автоматически освобождается здесь

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

Ответ 18+ 🔞

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

Смотри, вот тебе разбор полётов, чтобы наконец въехать, в чём, сука, разница.

Штука Стек (Stack) Куча (Heap)
Кто за неё отвечает? Всё автоматом, красота! Вошла функция — память под переменные выделилась. Вышла — всё само подмелось и выбросилось. Компилятор за тебя всё делает, как мамка. А тут, блядь, сам, мудила! Сам попросил (new, malloc) — сам и убери за собой (delete, free). Или доверься сборщику мусора, но он придёт когда захочет, как сантехник из ЖЭКа.
Скорость Охуенно быстрая. Всё как в хорошем фастфуде: сдвинул указатель стека — и готово, заказ принят. Медленная, как очередь в пенсионный фонд. Ещё найти свободное место надо, в многопоточности все друг другу мешают... Короче, возня.
Сколько можно? Мало, сука! Обычно несколько мегабайт. Напихаешь лишнего — получишь Stack Overflow и краш программы. Как в переполненный автобус полез — всех вывалило. Почти вся оперативка твоя! Хоть гигабайты тули. Ограничено только памятью компа и здравым смыслом.
Что там хранить? Всякую мелочёвку: локальные переменные, аргументы функций, адреса (указатели) на реальную движуху в куче. Всё, что живёт ровно до конца функции. Всё большое и долгоживущее: объекты, созданные через new, огромные массивы, данные, которые должны пережить вызов функции. Всё, что не влезло или не должно помереть сразу.
Порядок Идеальный, стерильный. Никакой фрагментации. А тут, ёпта, может такой бардак образоваться, как в моём гараже после зимы. Фрагментация, блядь! Иногда нужна уборка (дефрагментация).

Простое правило жизни: Мелкое и временное — в стек. Большое и на века (или неизвестно на сколько) — в кучу. Забыл это — готовься к утечкам памяти и падениям.

Пример на C, чтобы закрепить:

void example() {
    int onStack = 42; // Сидит в стекачке, уютно
    int *onHeap = (int*)malloc(sizeof(int)); // А вот это уже запрос в кучу, серьёзно
    *onHeap = 100;
    free(onHeap); // Не забудь, а то будет висеть в памяти, как призрак!
} // А 'onStack' тут просто испарится, даже не попрощавшись

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