Yığın və yığın nə və harada?

Proqramlaşdırma dillərində olan kitablar, dəyər növlərinin yığında yaradıldığını və bu iki şeyin nə olduğunu izah etmədən yığın üzərində istinad növlərini yaradılışını izah edir. Bunun üçün aydın bir izahat oxumamışdım. Bir yığın nə olduğunu başa düşürəm. Lakin

  • harada və nədir (fiziki olaraq real kompüter yaddaşında)?
  • Əməliyyat sistemi və ya dil ilə nə dərəcədə nəzarət olunur?
  • Həcmi nədir?
  • Hər birinin ölçüsünü nə müəyyən edir?
  • Nə daha sürətli edir?
7380
17 сент. set mattshane 17 sep . 2008-09-17 07:18 '08 saat 07:18 'da 2008-09-17 07:18
@ 25 cavab

Yığın bir icra mövzu üçün sıfır yer kimi kənara qoyulmuş bir yaddaşdır. Bir funksiya çağırıldığında, blok, yerli dəyişənlər və bəzi etimadnamələr üçün yığının üst hissəsində saxlanılır. Bu funksiya geri döndükdə, blok istifadə olunmur və funksiya növbəti dəfə istifadə edilə bilər. Yığın həmişə LIFO (birinci sırada sonuncu) sırasına aiddir; ən son qorunan blok həmişə buraxılacaq növbəti blokdur. Bu yığını izləmək üçün daha asan olur; yığını bir blok azad bir pointer tənzimlənməsi başqa bir şey deyil.

A yığın dinamik ayırma üçün ayrılmış yaddaşdır. Yığından fərqli olaraq, yığımdan bloklar ayırmaq və sərbəst buraxmaq üçün zorakı şablon yoxdur; Hər hansı bir zamanda bir blok seçə və istənilən vaxt buraxa bilərsiniz. Bu yığının hansı hissələrinin hər hansı bir zamanda paylanacağı və ya azad edildiyini izləmək üçün çox çətindir; Fərqli istifadə nümunələri üçün yığma performansını tənzimləmək üçün bir çox xüsusi paylayıcılar var.

Hər bir mövzu bir yığın qəbul edir, tətbiq üçün yalnız bir yığın adətən istifadə edilir (baxmayaraq ki, müxtəlif yerləşdirmə tipləri üçün bir neçə yığın var).

Birbaşa suallarınıza cavab vermək üçün:

Əməliyyat sistemi və ya dil ilə nə dərəcədə nəzarət olunur?

OS iş parçacığı yaratarkən hər bir sistem səviyyəli mövzu üçün yığını ayırır. Tipik olaraq, OS bir tətbiq üçün yığın ayırmaq üçün dil icra mühiti ilə çağırılır.

Həcmi nədir?

Yığın ipəyə əlavə olunur, beləliklə də ip yığından çıxdıqda, düzəldilir. Tətbiq iş vaxtında tətbiq edildikdə və ərizə (texniki proses) çıxıldıqdan sonra qaytarıldıqda bir yığın adətən ayrılır.

Hər birinin ölçüsünü nə müəyyən edir?

Yığın ölçüsü bir mövzu yaratarkən müəyyən edilir. Tətbiqə başlandıqda yığın ölçüsü müəyyən edilir, lakin lazım olduqda artırıla bilər (ayırıcı əməliyyat sistemindən daha çox yaddaş tələb edir).

Nə daha sürətli edir?

Yığın daha sürətlidır, çünki giriş nümunəsi ayırmaq və onu azad yaddaşdan (pointer / tamsayı sadəcə artır və ya kiçildərək) ehtiyatlı edir və yığın yerləşdirmə və ya azadla bağlı daha mürəkkəb maliyyə hesabatlarına malikdir. Bundan əlavə, yığındakı hər bir bayt tez-tez istifadə olunur, yəni prosessorun yaddaşında nümayiş etdirməyə meyllidir, bu da onu çox sürətli edir. Başqa bir yığım performansı çarəsidir ki, əsasən qlobal bir qaynaq olan yığın tipik olaraq çox yivli olmalıdır, yəni. Hər bir yayılma və sərbəstlik, bir qayda olaraq, proqramda "bütün" digər yığın çağırışları ilə sinxronlaşdırılmalıdır.

Təmiz nümayiş: 2019

5436
17 сент. Cavab Jeff Hill 17 sep verilir. 2008-09-17 07:52 '08 at 07:52 2008-09-17 07:52

Stack

  • Bir dəstə olaraq kompüter RAM-də saxlanılır.
  • Yığındakı dəyişənlər miqyasdan çıxır və avtomatik olaraq azad edilir.
  • Yığındakı dəyişənlərə nisbətən daha sürətli ayrılmaq.
  • Əsl yığın məlumatları strukturu ilə həyata keçirilir.
  • Yerli məlumatları saxlayır, parametrləri ötürmək üçün istifadə olunan ünvanları qaytarır.
  • Yığın çox hissəsi (əsasən sonsuz və ya çox dərin təkrarlanma, çox böyük dağıdıcılıqlar) istifadə edildikdə yığın daşması ola bilər.
  • Yığındakı məlumat göstəricilər olmadan istifadə edilə bilər.
  • Kompilyasiya hazırlamadan əvvəl nə qədər məlumat verdiyinizi dəqiq bilsəniz yığından istifadə edərdiniz və bu, çox böyük deyil.
  • Proqramınız başlandıqda adətən maksimum ölçülü artıq təyin olunur.

Heap:

border=0
  • Kompüter yaddaşında yığışma ilə eyni şəkildə saxlanılır.
  • C ++ 'da yığındakı dəyişənlər əllə məhv edilməli və əhatə dairəsinə düşməməlidir. Data delete , delete[] və ya free .
  • Yığındakı dəyişənlərə nisbətlə ayırmaq daha asandır.
  • Proqram tərəfindən istifadəyə verilən bir məlumat bloğu ayırmaq tələbi ilə istifadə olunur.
  • Bəzi ayırmalar və istisnalar olduqda parçalanma ola bilər.
  • C ++ və ya C-də, yığındakı məlumatlar göstəricilər tərəfindən göstəriləcək və müvafiq olaraq new və ya malloc veriləcəkdir.
  • Çox tampon tələb olunarsa, yayılmaması ola bilər.
  • Çalışma müddətində nə qədər məlumatın lazım olduğunu və ya bir çox məlumatın ayrılmasına ehtiyac duyarsanız, bir qrupdan istifadə edərsiniz.
  • Yaddaş sızıntısından cavabdehdir.

Məsələn:

2164
17 сент. Cavab Brian R. Bondy tərəfindən verilir . 2008-09-17 07:20 '08 at 07:20 'da 2008-09-17 07:20

Ən əhəmiyyətli nöqtə, yığın və yığın yaddaş ayırma üsulları üçün ümumi şərtlərdir. Onlar müxtəlif yollarla həyata keçirilə bilər və bu şərtlər əsas anlayışlara tətbiq edilir.

  • Elementlərin yığında elementlər birinin üstünə yerləşdirilib, orada yerləşdirildikləri sırada yerləşdirilir və yalnız yuxarı hissəni (hər şeyi əyməksiz) götürə bilərsiniz.

    2019

1294
19 марта '09 в 17:38 2009-03-19 17:38 Cavab 19 : 00-19 : 00, saat 17 : 38 -də thomasrutter tərəfindən verilmişdir 2009-03-19 17:38

(Bu cavabı daha çox və ya daha az aldatmış başqa bir sualdan köçürdüm.)

Sualınızın cavabı xüsusi həyata keçirilir və kompilyator və prosessor arxitekturaları arasında dəyişə bilər. Ancaq bu sadə bir şərhdir.

  • Hər iki yığın və yığın, əsas əməliyyat sistemindən ayrılan yaddaş zonalarıdır (tez-tez virtual yaddaş, tələb olunan fiziki yaddaşla əlaqələndirilir).
  • Çox işıqlı bir mühitdə, hər bir mövzu öz tam müstəqil yığını olacaq, lakin yığınları bölüşdürəcəklər. Paralel giriş yığın üzərində nəzarət edilməli və yığında mümkün deyildir.

Bir yığın

  • Yığın istifadə olunan və azad blokların əlaqəli bir siyahısını ehtiva edir. Yeni blok malloc ( new və ya malloc ) pulsuz bloklardan birinə uyğun bir blok yaratmaqla təmin olunur. Bu yığındakı blokların siyahısını yeniləmək tələb olunur. Bir yığındakı bloklar haqqında bu meta məlumatı, həm də hər bir blokun qarşısında, kiçik bir ərazidə, bir yığında da saxlanılır.
  • Yığın böyüdükcə yeni bloklar tez-tez aşağı ünvanlardan daha yüksək ünvanlara ayrılır. Beləliklə, yaddaş yığımı kimi ölçüdə böyüyən yaddaş bloklarının yığını kimi yığın düşünə bilərsiniz. Çığırma paylanması üçün çox kiçik olsa, ölçüsü əsasən əsas əməliyyat sistemindən daha çox yaddaş əldə etməklə artırıla bilər.
  • Çox kiçik blokları ayırma və sərbəstləşdirmək, istifadə edilən bloklar arasında bir-birinə qarışmış bir çox kiçik boş blokun olduğu bir vəziyyətdə bir yığını tərk edə bilər. Böyük bir blok ayırmağı tələb edə bilər, çünki azad bloklardan heç biri, azad blokların birləşdirilmiş ölçüsü kifayət qədər böyük ola bilsə də, paylama tələbini təmin etmək üçün kifayət qədər böyük deyil. Buna yığın parçalanması deyilir.
  • Pulsuz bloka bitişik blok istifadə edildikdə, yeni bir pulsuz blok yığın parçalanmasını effektiv şəkildə azaldacaq daha böyük bir azad blok yaratmaq üçün bitişik bir pulsuz blokla birləşdirilə bilər.

2019

681
31 июля '09 в 18:54 2009-07-31 18:54 Cavab Martin Liversage tərəfindən 31 İyul '09 saat 18:54 'da verildi. 2009-07-31 18:54

Aşağıdakı kodda C #

370
ответ дан Snowcrash 09 нояб. '12 в 15:28 2012-11-09 15:28

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

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

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

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

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

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

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

194
ответ дан Tom Leys 17 сент. '08 в 7:27 2008-09-17 07:27

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

"Static" (AKA статически выделенные) переменные не выделяются в стеке. Не думайте так - многие люди делают это только потому, что "статические" звучат так же, как "стек". Они фактически не существуют ни в стеке, ни в куче. Это часть того, что называется сегментом данных .

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

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

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

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

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

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

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

174
ответ дан davec 11 нояб. '12 в 2:03 2012-11-11 02:03

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

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

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

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

159
ответ дан Don Neufeld 17 сент. '08 в 7:48 2008-09-17 07:48

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

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

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

128
ответ дан bk1e 17 сент. '08 в 10:16 2008-09-17 10:16

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

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

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

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

108
ответ дан Daniel Papasian 17 сент. '08 в 7:29 2008-09-17 07:29

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

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

107
ответ дан Heath 17 сент. '08 в 7:57 2008-09-17 07:57

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

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

2019

ответ дан Shreyos Adikari 11 июня '14 в 22:42 2014-06-11 22:42

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

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

88
ответ дан Peter 19 марта '09 в 18:55 2009-03-19 18:55

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

Куча - это область памяти. Динамические распределения памяти сделаны из (явных "новых" или "распределяющих" вызовов). Это специальная структура данных, которая может отслеживать блоки памяти разных размеров и их статус распределения.

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

85
ответ дан TED 19 марта '09 в 18:13 2009-03-19 18:13

Из WikiAnwser.

Stack

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

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

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

Heap

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

79
ответ дан devXen 02 апр. '09 в 4:25 2009-04-02 04:25

Stack

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

Heap

  • Доступны переменные во всем мире
  • Ограничение размера памяти
  • (Относительно) медленный доступ
  • Нет гарантированного эффективного использования пространства, память может со временем фрагментироваться, когда выделяются блоки памяти, а затем освобождается
  • Вы должны управлять памятью (вы отвечаете за выделение и освобождение переменных)
  • Переменные могут быть изменены с помощью realloc()
50
ответ дан unknown 30 янв. '14 в 9:33 2014-01-30 09:33

Хорошо, просто и вкратце, они означают упорядоченные и не упорядоченные ...!

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

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

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

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

2019

ответ дан Alireza 18 июля '17 в 18:04 2017-07-18 18:04

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

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

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

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

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

2019

35
ответ дан jlettvin 27 марта '15 в 22:55 2015-03-27 22:55

Короче

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


В деталях

Стек

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

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

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


Куча

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

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

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

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

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


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

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

2019

ответ дан Abrar Jahin 02 мая '16 в 15:16 2016-05-02 15:16
  • Введение

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

На рисунке 4-1 показана физическая память, которая была абстрагирована и управляется ОС, используя концепцию виртуальной памяти. Виртуальная память - это абстрактный вид физической памяти, управляемый ОС. Виртуальная память - это просто серия виртуальных адресов, и эти виртуальные адреса преобразуются ЦП в физический адрес, когда это необходимо.

Рисунок 4-1. Запоминание памяти CLR

2019

29
ответ дан kokabi 10 нояб. '14 в 20:22 2014-11-10 20:22

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

24
ответ дан Yousha Aleayoub 14 сент. '17 в 20:32 2017-09-14 20:32

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

2019

ответ дан Maxim Akristiniy 17 дек. '15 в 18:08 2015-12-17 18:08

Так как некоторые ответы поменялись, я собираюсь внести свой вклад.

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

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

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

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

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

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

21
ответ дан shakurov 02 марта '15 в 4:29 2015-03-02 04:29

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

стек

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

отвал

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

Интересная заметка:

  • Если бы вызовы функций были сохранены в куче, это привело бы к двум беспорядочным точкам:
    1. Благодаря последовательному хранению в стеке выполнение выполняется быстрее. Хранение в куче привело бы к огромному расходу времени, что замедлило бы выполнение всей программы.
    2. Если бы функции хранились в куче (грязное хранилище, на которое указывает указатель), не было бы никакого способа вернуться назад к адресу вызывающей стороны (какой стек дает из-за последовательного хранения в памяти).
9
ответ дан Pankaj Kumar Thapa 15 нояб. '17 в 21:27 2017-11-15 21:27

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

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

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

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

Использование стека выполняется быстрее:

  • Это аппаратное обеспечение, и даже push/pop очень эффективны.
  • malloc требует входа в режим ядра, используйте lock/semaphore (или другие примитивы синхронизации), выполняющие некоторый код и управляющие некоторыми структурами, необходимыми для отслеживания выделения.
9
ответ дан ingconti 28 июля '17 в 1:14 2017-07-28 01:14

Другие вопросы по меткам > или Задайте вопрос