Што і дзе знаходзяцца стэк і куча?

Кнігі на мовах праграмавання тлумачаць, што тыпы значэнняў ствараюцца ў стэку, а спасылачныя тыпы ствараюцца ў кучы, не тлумачачы, што гэта за дзве рэчы. Я не прачытаў выразнага тлумачэння гэтага. Я разумею, што такое стэк. але,

  • дзе і што яны (фізічна ў рэальнай кампутарнай памяці)?
  • У якой ступені яны кантралююцца аперацыйнай сістэмай або мовай?
  • Які іх аб'ём?
  • Што вызначае памер кожнага з іх?
  • Што робіць хутчэй?
7380
17 сент. зададзены mattshane 17 сент. 2008-09-17 07:18 '08 у 7:18 2008-09-17 07:18
@ 25 адказаў

Стэк - гэта памяць, адкладзеная ў якасці прасторы скрыжавалі для патоку выканання. Калі выклікаецца функцыя, блок зарэзерваваны у верхняй частцы стэка для лакальных зменных і некаторых уліковых дадзеных. Калі гэтая функцыя вяртаецца, блок становіцца невыкарыстоўвальнай і можа выкарыстоўвацца пры наступным выкліку функцыі. Стэк заўсёды зарэзерваваны ў парадку LIFO (апошні ў першым парадку); самы апошні зарэзерваваны блок заўсёды з'яўляецца наступным блокам, які павінен быць вызвалены. Гэта спрашчае адсочванне стэка; вызваленне блока з стэка з'яўляецца не больш чым карэкціроўкай аднаго паказальніка.

Куча - гэта памяць, выдзеленая для дынамічнага размеркавання. У адрозненне ад стэка, няма ніякага прымусовага шаблону для размеркавання і вызвалення блокаў з кучы; вы можаце вылучыць блок у любы час і вызваліць яго ў любы час. Гэта значна ўскладняе адсочванне таго, якія часткі кучы размеркаваны або вызваленыя ў любы момант часу; існуе мноства наладжвальных кучевых размеркавальнікаў для налады прадукцыйнасці кучы для розных шаблонаў выкарыстання.

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

Каб адказаць на вашы пытанні наўпрост:

У якой ступені яны кантралююцца аперацыйнай сістэмай або мовай?

АС вылучае стэк для кожнага патоку сістэмнага ўзроўню пры стварэнні патоку. Звычайна АС выклікаецца асяроддзем выканання мовы для вылучэння кучы для прыкладання.

Які іх аб'ём?

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

Што вызначае памер кожнага з іх?

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

Што робіць хутчэй?

Стэк хутчэй, таму што шаблон доступу робіць трывіяльным вылучэнне і вызваленне памяці ад яго (паказальнік / цэлае проста павялічваецца ці памяншаецца), а куча мае значна больш складаную бухгалтарскую справаздачнасць, звязаную з размеркаваннем або вызваленнем. Акрамя таго, кожны байт у стэку часта выкарыстоўваецца паўторна, што азначае, што ён мае тэндэнцыю адлюстроўвацца ў кэш працэсара, што робіць яго вельмі хуткім. Яшчэ адным хітом прадукцыйнасці для кучы з'яўляецца тое, што куча, якая з'яўляецца галоўным чынам глабальным рэсурсам, як правіла, павінна быць многопотоковой бяспекай, г.зн. Кожнае размеркаванне і вызваленне павінна быць - як правіла, сінхранізаваны з "усімі" іншымі зваротамі кучы ў праграме.

Выразная дэманстрацыя: 2019

5436
17 сент. адказ дадзены Jeff Hill 17 сент. 2008-09-17 07:52 '08 у 7:52 2008-09-17 07:52

Stack

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

Heap:

border=0
  • Захоўваецца ў аператыўнай памяці кампутара гэтак жа, як і стэк.
  • У З ++ зменныя ў кучы павінны быць знішчаныя ўручную і ніколі не выпадаюць з вобласці бачнасці. Дадзеныя вызваляюцца з дапамогай delete , delete[] або free .
  • Павольней вылучаць у параўнанні з зменнымі ў стэку.
  • Выкарыстоўваецца па патрабаванні для вылучэння блока дадзеных для выкарыстання праграмай.
  • Можа мець фрагментацыю, калі ёсць шмат размеркаванняў і вызваленняў.
  • У З ++ або C дадзеныя, створаныя ў кучы, будуць пазначаны паказальнікамі і выдзелены адпаведна new ці malloc .
  • Можа мець адмова ў размеркаванні, калі патрабуецца вылучэнне занадта вялікага аб'ёму буфера.
  • Вы б выкарыстоўвалі кучу, калі не ведаеце дакладна, колькі дадзеных вам спатрэбіцца падчас выканання або калі вам трэба вылучыць шмат дадзеных.
  • Адказны за уцечку памяці.

прыклад:

2164
17 сент. адказ дадзены Brian R. Bondy 17 сент. 2008-09-17 07:20 '08 ў 7:20 2008-09-17 07:20

Найбольш важным момантам з'яўляецца тое, што куча і стэк ўяўляюць сабой агульныя тэрміны для спосабаў вылучэння памяці. Яны могуць быць рэалізаваны па-рознаму, і гэтыя тэрміны дастасавальныя да асноўных паняццях.

  • У стэку элементаў элементы размяшчаюцца адзін над іншым у тым парадку, у якім яны былі там размешчаныя, і вы можаце выдаліць толькі верхнюю частку (без перакульвання ўсёй рэчы).

    2019

1294
19 марта '09 в 17:38 2009-03-19 17:38 адказ дадзены thomasrutter 19 сакавіка '09 у 17:38 2009-03-19 17:38

(Я перамясціў гэты адказ з іншага пытання, які быў больш-менш падманам гэтага.)

Адказ на ваша пытанне спецыфічны для рэалізацыі і можа адрознівацца ў розных кампілятарах і архітэктурах працэсараў. Аднак гэта спрошчанае тлумачэнне.

  • Абодва стэка і куча з'яўляюцца абласцямі памяці, вылучанымі з базавай аперацыйнай сістэмы (часта віртуальная памяць, якая па запыце адлюстроўваецца ў фізічную памяць).
  • У шматструменнай асяроддзі кожны струмень будзе мець свой уласны цалкам незалежны стэк, але яны будуць падзяляць кучу. Паралельны доступ павінен кантралявацца ў кучы і немагчымы ў стэку.

куча

  • Куча змяшчае звязаны спіс выкарыстоўваюцца і свабодных блокаў. Новыя размеркавання ў кучы (на new ці malloc ) задавальняюцца шляхам стварэння падыходнага блока з аднаго з свабодных блокаў. Гэта патрабуе абнаўлення спісу блокаў ў кучы. Гэтая метаінформаціі аб блоках ў кучы таксама захоўваецца ў кучы часта ў невялікай вобласці непасрэдна перад кожным блокам.
  • Па меры росту кучы новыя блокі часта вылучаюцца з ніжніх адрасоў ў бок больш высокіх адрасоў. Такім чынам, вы можаце думаць аб кучы як кучы блокаў памяці, якія растуць у памеры па меры выдзялення памяці. Калі куча занадта малая для размеркавання, памер часта можа быць павялічаны за кошт набыцця большага аб'ёму памяці з базавай аперацыйнай сістэмы.
  • Вылучэнне і вызваленне шматлікіх невялікіх блокаў можа пакінуць кучу ў стане, у якім ёсць шмат невялікіх свабодных блокаў, перамежных паміж выкарыстоўванымі блокамі. Запыт на вылучэнне вялікага блока можа пацярпець няўдачу, таму што ні адзін з вольных блокаў не з'яўляецца дастаткова вялікім, каб задаволіць запыт на размеркаванне, нават калі аб'яднаны памер свабодных блокаў можа быць дастаткова вялікім. Гэта называецца фрагментацыяй кучы.
  • Калі які выкарыстоўваецца блок, сумежны са свабодным блокам, вызваляецца, новы свабодны блок можа быць аб'яднаны з сумежных вольным блокам для стварэння большага вольнага блока, эфектыўна паменшвалага фрагментацыю кучы.

2019

681
31 июля '09 в 18:54 2009-07-31 18:54 адказ дадзены Martin Liversage 31 ліпеня '09 а 18:54 2009-07-31 18:54

У наступным кодзе З #

var _tmr = window._tmr || (window._tmr = []);_tmr.push({id: "2334768", type: "pageView", start: (new Date()).getTime()});(function (d, w, id) {  if (d.getElementById(id)) return;  var ts = d.createElement("script"); ts.type = "text/javascript"; ts.async = true; ts.id = id;  ts.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//top-fwz1.mail.ru/js/code.js";  var f = function () {var s = d.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ts, s);};  if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); }})(document, window, "topmailru-code");