Коротко
Стек використовується для статичного розподілу пам’яті та купа динамічного розподілу пам’яті, що зберігаються в оперативній пам’яті комп'ютера.
Детально
Стек
Стек - це структура даних "LIFO" (останнє, перше), яка керується та оптимізується процесором досить близько. Кожен раз, коли функція оголошує нову змінну, її "натискають" на стек. Потім кожного разу, коли функція виходить, всі змінні, висунуті на стек цією функцією, звільняються (тобто видаляються). Після звільнення змінної стека ця область пам'яті стає доступною для інших змінних стека.
Перевага використання стека для зберігання змінних полягає в тому, що пам'ять керована для вас. Вам не потрібно виділяти пам'ять вручну або звільняти її, як тільки вона вам більше не потрібна. Більше того, оскільки процесор так ефективно організовує стек-пам'ять, читання та запис змінних в стек дуже швидко.
Більше можна знайти тут .
Куча
Купа - це область пам’яті вашого комп'ютера, яка не управляється автоматично для вас і не так щільно управляється процесором. Це більш вільно плаваюча область пам'яті (і є більшою). Щоб розподілити пам'ять на купі, потрібно використовувати malloc () або calloc (), які є вбудованими функціями C. Виділивши пам'ять на купі, ви несете відповідальність за використання free () для розміщення цієї пам'яті, коли вона вам більше не потрібна.
Якщо цього не зробити, у вашій програмі з’явиться те, що відомо як витік пам'яті. Тобто, пам'ять у купі все одно буде відкладена (і не буде доступна для інших процесів). Як ми побачимо в розділі налагодження, є інструмент під назвою Valgrind, який може допомогти вам виявити витоки пам'яті.
На відміну від стека, купа не має обмежень щодо розміру змінних розмірів (крім очевидних фізичних обмежень вашого комп'ютера). Пам’ять купи трохи повільніше читати і записувати в неї, тому що для доступу до пам'яті в купі потрібно використовувати вказівники. Про покажчики ми поговоримо найближчим часом.
На відміну від стека, змінні, створені на купі, доступні будь-якій функції в будь-якій точці вашої програми. Змінні купи по суті є глобальними.
Більше можна знайти тут .
Змінні, виділені в стеці, зберігаються безпосередньо в пам'яті, і доступ до цієї пам'яті відбувається дуже швидко, і з її розподілом відбувається, коли програма компілюється. Коли функція або метод викликає іншу функцію, яка по черзі викликає іншу функцію тощо, виконання всіх цих функцій залишається призупиненим, поки сама остання функція не поверне своє значення. Стек завжди зарезервований у порядку LIFO, останній зарезервований блок - це завжди наступний блок, який повинен бути звільнений. Це робить насправді простим відстеження стека, звільнення блоку зі стека - це не що інше, як коригування одного вказівника.
Змінні, що виділяються в купі, виділяють пам'ять під час виконання, а доступ до цієї пам'яті дещо повільніше, але розмір купи обмежений лише розміром віртуальної пам'яті. Елементи купи не залежать один від одного і завжди можна отримати доступ довільно в будь-який час. Ви можете виділити блок у будь-який час та звільнити його в будь-який час. Це робить набагато складніше відслідковувати, які частини купи виділяються чи вільні в будь-який момент часу.
Ви можете використовувати стек, якщо точно знаєте, скільки даних потрібно виділити до часу компіляції, і він не надто великий. Ви можете використовувати купу, якщо ви точно не знаєте, скільки даних вам знадобиться під час виконання або якщо вам потрібно виділити багато даних.
У багатопотокової ситуації кожна нитка матиме власний повністю незалежний стек, але вони поділять купу. Стек є потоковим, а купа - специфічною для програми. Стек важливо враховувати при обробці винятків та виконанні потоків.
Кожен потік отримує стек, хоча для програми зазвичай є лише одна купа (хоча не рідкість наявність декількох груп для різних типів розподілу).
Якщо під час виконання програми потрібна більша купа, вона може виділяти пам'ять з вільної пам'яті, а якщо стеку потрібна пам'ять, вона може виділяти пам'ять із вільної пам'яті, виділеної для програми.
Навіть, детальніше тут і тут .
Тепер приходьте до відповідей вашого питання .
Наскільки вони контролюються ОС або мовою виконання?
ОС створює стек для кожного потоку на рівні системи під час створення потоку. Зазвичай ОС викликається мовою виконання, щоб виділити купу для програми.
Більше можна знайти тут .
Яка сфера їх застосування?
Вже дано вгорі.
"Ви можете використовувати стек, якщо точно знаєте, скільки даних потрібно виділити перед тим, як час компіляції, і він не надто великий. Ви можете використовувати купу, якщо ви точно не знаєте, скільки даних вам знадобиться під час виконання або якщо вам потрібно виділити багато даних ".
Більше можна знайти тут .
Від чого залежить розмір кожного з них?
Розмір стека встановлюється ОС при створенні потоку. Розмір купи встановлюється при запуску програми, але він може зростати в міру необхідності місця (алокатор вимагає більше оперативної пам'яті).
Що робить одного швидше?
Розподіл стека відбувається набагато швидше, оскільки все це дійсно - переміщення покажчика стека. Використовуючи пули пам'яті, ви можете отримати порівняну продуктивність із розподілу купи, але це має незначну додаткову складність та власні головні болі.
Крім того, стек проти купи - це не лише врахування продуктивності; це також багато розповідає про очікуваний термін експлуатації об'єктів.
Деталі можна знайти тут .