Что такое стек? Что такое стек в рисовании


Основные принципы программирования: стек и куча

Рассказывает Аарон Краус 

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

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

Стек

Стек — это область оперативной памяти, которая создаётся для каждого потока. Он работает в порядке LIFO (Last In, First Out),  то есть последний добавленный в стек кусок памяти будет первым в очереди на вывод из стека. Каждый раз, когда функция объявляет новую переменную, она добавляется в стек, а когда эта переменная пропадает из области видимости (например, когда функция заканчивается), она автоматически удаляется из стека. Когда стековая переменная освобождается, эта область памяти становится доступной для других стековых переменных.

Из-за такой природы стека управление памятью оказывается весьма логичным и простым для выполнения на ЦП; это приводит к высокой скорости, в особенности потому, что время цикла обновления байта стека очень мало, т.е. этот байт скорее всего привязан к кэшу процессора. Тем не менее, у такой строгой формы управления есть и недостатки. Размер стека — это фиксированная величина, и превышение лимита выделенной на стеке памяти приведёт к переполнению стека. Размер задаётся при создании потока, и у каждой переменной есть максимальный размер, зависящий от типа данных. Это позволяет ограничивать размер некоторых переменных (например, целочисленных), и вынуждает заранее объявлять размер более сложных типов данных (например, массивов), поскольку стек не позволит им изменить его. Кроме того, переменные, расположенные на стеке, всегда являются локальными.

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

Куча

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

Вы взаимодействуете с кучей посредством ссылок, обычно называемых указателями — это переменные, чьи значения являются адресами других переменных. Создавая указатель, вы указываете на местоположение памяти в куче, что задаёт начальное значение переменной и говорит программе, где получить доступ к этому значению. Из-за динамической природы кучи ЦП не принимает участия в контроле над ней; в языках без сборщика мусора (C, C++) разработчику нужно вручную освобождать участки памяти, которые больше не нужны. Если этого не делать, могут возникнуть утечки и фрагментация памяти, что существенно замедлит работу кучи.

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

Заключение

Вот вы и познакомились с понятиями стека и кучи. Вкратце, стек — это очень быстрое хранилище памяти, работающее по принципу LIFO и управляемое процессором. Но эти преимущества приводят к ограниченному размеру стека и специальному способу получения значений. Для того, чтобы избежать этих ограничений, можно пользоваться кучей — она позволяет создавать динамические и глобальные переменные — но управлять памятью должен либо сборщик мусора, либо сам программист, да и работает куча медленнее.

Перевод статьи «Programming Concepts: The Stack and the Heap»

Иван Бирюков, главный по новостям

Наши тесты для вас:— Тест на знание сленга веб-разработчиков.— Что вы знаете о работе мозга?— А вы точно программист?

tproger.ru

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

– Автор: Игорь (Администратор)

Что такое стек?В рамках данной статьи, я расскажу вам что такое стек, а так же для чего он нужен и где применяется.

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

Стек (stack) - это метод представления однотипных данных (можно просто называть типом) в порядке LIFO (Last In - First Out, что означает "первый вошел - последний вышел"). Стоит упомянуть, что в русской технике его так же называют "магазином". И речь тут не о продуктовом магазине, а о рожке с патронами для оружия, так как принцип весьма схож - первый вставленный патрон будет использован последним.

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

Чтобы лучше понять, приведу жизненный пример. Допустим у вас есть стопка листов. Каждый исписанный лист вы кладете рядом, а каждый следующий поверх остальных. Чтобы достать к примеру, самый первый лист из полученной стопки, вам необходимо вытащить все остальные листы. Вот по этому же самому принципу и устроен stack. То есть, каждый последний добавленный элемент становится верхним и чтобы достать, к примеру, самый первый элемент необходимо вытащить все остальные.

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

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

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

Какие операции у stack? Основных операций всего две:

1. Добавление элемента в вершину стека называется push

2. Извлечения верхнего элемента называется pop

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

Как организуется стек? Обычно стек реализуется двумя вариантами:

1. С помощью массива и переменной, которая указывает на ячейку с вершиной стека

2. С помощью связанных списков

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

Теперь, вы знаете что такое стек, а так же зачем он нужен и для чего применяется.

  • Что такое электронная подпись?
  • Что такое Хэш?
Добавить комментарий / отзыв

ida-freewares.ru

Стек

Стек

Стек - это такая структура данных в памяти, которая используется для временного хранения информации. Программа может поместить информацию в стек (команда PUSH) или извлечь ее из стека (команда POP). Данные в стеке упорядочиваются специальным образом. Извлекаемый из стека элемент данных - это всегда тот элемент, который был записан туда последним. Такая организация хранения данных сокращенно обозначается LIFO (Last In, First Out - последний поступивший удаляется первым). Если мы поместим в стек два элемента: сначала A, а затем B, то при первом обращении к стеку извлекается элемент B, а при следующем - A. Информация выбирается из стека в обратном по отношению к записи порядке.

Стек можно противопоставить очереди, похожей на ту, что обычно образуется в почтовом отделении или в магазине. Очередь - это структура данных, организованная по принципу "первый поступивший удаляется первым" (First In, First Out - FIFO). Первый человек, вставший в очередь, первым ее и покинет. Очередь и стек полностью противоположны.

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

На рис.2.19 показан пример стека. Рисунок 2.19а иллюстрирует состояние стека после того, как туда были последовательно записаны значения A, B и C. Указатель стека указывает на содержимое вершины стека TOS, в данном случае на C. После этого в стек записывается еще один элемент - D (рис.2.19б). Команда PUSH уменьшает на 1 значение указателя стека SP, который теперь указывает на значение содержимого вершины TOS, равное D. Как всегда, указатель стека указывает на последний записанный в стек элемент.

Рисунок 2.19в иллюстрирует состояние стека после выполнения команды POP. Эта команда считала из стека элемент D. Считанное из стека значение помещается командой POP в специальную область. Если в данном случае выполнялась команда POP AX, то микропроцессор запишет значение D в регистр AX (это уже дополнительный аспект, который будет подробно рассмотрен в следующей главе). Указатель стека увеличивается этой командой на 1 и будет указывать теперь на новое значение содержимого вершины TOS, равное С. Обратите внимание на то, что выборка элементов из стека производится по описанному выше принципу LIFO. Последним помещенным в стек элементом был D и он же был первым, считанным из стека.

Заметим также, что хотя значение D и продолжает храниться в памяти, оно уже больше не является частью стека. Логическая граница стека совпадает с ячейкой, адрес которой хранится в указателе стека. В данном случае вершина стека находится ниже ячейки, содержащей элемент D.

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

В рассмотренных выше примерах подразумевалась определенная организация стека, реализованная в микропроцессоре 8088. При этом указатель стека всегда указывал на текущее значение содержимого вершины стека. Команда PUSH уменьшает, а команда POP увеличивает значение указателя стека на 1. Стек растет в направлении меньших значений адресов памяти. Основание стека имеет адрес паямти больший, чем его вершина. Если, как и на рис.2.19, изображать ячейки стека с меньшими адресами сверху, то вершина стека будет располагаться в верхней части рисунка.

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

Каждая команда CALL вызывает запись в стек - записывает в стек адрес возврата. Команда RET, подобно команде POP, считывает из стека адрес возврата и помещает его в указатель команд. Таким образом, в микропроцессоре 8088 стек используется для хранения адресов возврата, что позволяет осуществлять вложение подпрограмм. Что такое вложение подпрограмм? Рисунок 2.20 иллюстрирует пример вложения подпрограмм.

Приведенная на рис.2.20 программа не имеет реального смысла и будет использоваться как пример вложения подпрограмм. На рис.2.20а показано состояние стека перед выполнением программы. По мере выполнения основной программы, начинающейся с метки MAIN, происходит вызов подпрограммы SUBROUTINE_A. При этом, как видно из рис.2.20б, микропроцессор записывает в стек адрес возврата, равный 103. В процессе своего выполнения подпрограмма SUBROUTINE_A вызывает подпрограмму SUBROUTINE_B. Команда вызова записывает в стек соответствующий адрес возрвата, равный 108, в подпрограмму SUBROUTINE_A, как это показано на рис.2.20в. В момент завершения подпрограммы SUBROUTINE_B команда возврата считывает из стека значение 108 (рис.2.20г). Процессор в соответствии с командой возврата помещает это значение в указатель команд. Как видно из приведенного примера, команда в ячейке с адресом 108 относится к подпрограмме SUBROUTINE_A и является следующей после команды вызова подпрограммы SUBROUTINE_B. При этом работа подпрограммы SUBROUTINE_A завершается. Команда возврата перезаписывает значение 103 из стека в указатель команд. Команда в ячейке с адресом 103 относится к головной программе инепосредственно следует за командой вызова подпрограммы SUBROUTINE_A.

В приведенном на рис.2.20 примере основным является вложение подпрограмм. Одна подпрограмма может вызывать другую, а команды возврата всегда обеспечивают возвращение в нужное место. Единственное, что ограничивает глубину вложения подпрограмм (число подпрограмм, вызывающих другие подпрограммы) - это объем стека. До тех пор, пока в стеке имеется место для хранения еще одного адреса возврата, могут осуществляться вызов и вложение еще одной подпрограммы. Организация стека по принципу LIFO обеспечивает правильное упорядочение адресов возврата.

Приведенная на рис.2.20 программа иллюстрирует также использование псевдокоманды языка ассемблера PROC. Оператор PROC используется ассемблером для идентификации подпрограмм. Как будет показано в дальнейшем, ассемблеру нужна информация о том, как далеко располагается подпрограмма и как должен осуществляться возврат в точку вызова подпрограммы. Параметр NEAR идентифицирует такую подпрограмму, которая расположена недалеко от точки ее вызова. В дальнейшем мы еще вернемся к оператору PROC, когда будем подробно рассматривать выполнение команд CALL и JMP.

aleksandrypolyakov.narod.ru


Смотрите также