Подтвердить что ты не робот

Управление памятью в Форте

Итак, я просто изучаю Forth, и мне было любопытно, может ли кто-нибудь помочь мне понять, как работает управление памятью. На данный момент у меня есть (некоторые) опыт работы с парадигмой C-стек-vs-куча.

Из того, что я понимаю, можно выделить в словаре или в куче. Является ли словарь быстрее/предпочтительнее, чем стек в C? Но, в отличие от C, не существует областей и автоматической рекультивации стека, поэтому мне интересно, использует ли только словарь для глобальных структур данных (если вообще).

Насколько куча идет, это в значительной степени похоже на C? Является ли управление кучей стандартным (ANS), или оно определено реализацией?

4b9b3361

Ответ 1

Это не словарь или куча - эквивалент кучи - это словарь. Тем не менее, с серьезным ограничением, что он действует скорее как стек, чем куча - в конец словаря добавляются новые слова (выделение ALLOT и освобождение FORGET или FREE (но освобождение всех новых слов - действие больше похоже на несколько СОЗ)).

Реализация может управлять макетом памяти и тем самым реализовывать традиционную кучу (или сборку мусора). Примером может служить ПРОФЕССИОНАЛЬНАЯ реализация структуры данных кучи для контировки памяти (1984). Другая реализация - Динамические кучи памяти для Quartus Forth (2000).

Много зависит от реализации или расширения. Например, макет памяти часто используется с двумя блочными буферами (местоположение BLOCK и TIB), буфером ввода текста и значениями и низкоуровневыми/примитивными функциями языка, в младшей части, словарь в средний (рост вверх) и стек возврата и стек параметров в верхней части 1.

Адрес первого доступного байта над словарем возвращается HERE (он изменяется по мере расширения словаря).

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

Предпочтительным режимом работы является использование стека как можно больше вместо локальных переменных или кучи.

1 p. 286 (о конкретном издании Forth, MMSFORTH) в главе "FORTH Memory, Dictionary и Vocabularies", Forth: текст и ссылка. Маллон Г. Келли и Николас Шпиес. ISBN 0-13-326349-5/0-13-326331-2 (pbk.). 1986 г. Прентис-Холл.

Ответ 2

На фундаментальный вопрос, возможно, не ответили так, как этого требовал бы новый пользователь Forth, поэтому я возьму его на выполнение.

Память в Форте может быть очень зависимой от цели, поэтому я ограничу описание самой простой моделью, которая является плоским пространством памяти, где код и данные живут вместе счастливо. (в отличие от сегментированных моделей памяти или FLASH-памяти для кода и ОЗУ для данных или других более сложных моделей)

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

На самом фундаментальном уровне память выделяется просто путем изменения значения переменной указателя словаря. (иногда называемый DP)

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

Как уже упоминалось, слово Forth 'HERE' возвращает следующий доступный адрес в пространстве словаря. Не было упомянуто, что ЗДЕСЬ определяется путем извлечения значения переменной DP. (системная зависимость здесь, но полезная для описания)

В Forth "ЗДЕСЬ" может выглядеть так:

: ЗДЕСЬ (- addr) DP @;

Что это.

Чтобы выделить некоторую память, нам нужно перемещаться ЗДЕСЬ вверх, и мы делаем это со словом "ALLOT".

Определение Forth для "ALLOT" просто берет число из стека параметров и добавляет его к значению в DP. Таким образом, это не что иное, как:

: ALLOT (n -) DP +!;\'+!' добавляет n к переменной содержимого DP

ALLOT используется системой FORTH, когда мы создаем новое определение, чтобы то, что мы создали, было безопасно в памяти "ALLOTed".

То, что не сразу становится очевидным, - это то, что ALLOT может принимать отрицательное число, поэтому можно перемещать указатель слова вверх или вниз. Таким образом, вы можете выделить некоторую память и вернуть ее так:

HEX 100 ALLOT

И освободите его так:

HEX -100 ALLOT

Все это говорит о том, что это самая простая форма управления памятью в системе Forth. Пример того, как это можно использовать, можно увидеть в определении слова "БУФЕР":

: BUFFER: (n -) СОЗДАТЬ ALLOT;

'BUFFER:' "создает" новое имя в словаре (создает использование выделения для создания пробела для имени), затем ALLOTs n байтов памяти сразу после имени и любых связанных служебных байт, которые может использовать ваша система Forth

Итак, теперь, чтобы выделить блок именованной памяти, мы просто набираем:

MARKER FOO\отметьте, где память заканчивается прямо сейчас

HEX 2000 BUFFER: IN_BUFFER

Теперь у нас есть буфер размером 8 Кбайт, называемый IN_BUFFER. Если бы захотелось вернуть это пространство в Стандартном Форте, мы могли бы набрать "FOO" и все, что было выделено в словаре после того, как FOO будет удалено из системы Forth.

Но если вы хотите временное пространство памяти, все, что доступно выше "ЗДЕСЬ", можно использовать!

Итак, вы можете просто указать адрес и использовать его, если хотите, чтобы этот

: MYMEMORY здесь 200 +;\MYMEMORY указывает на выделенную память выше ЗДЕСЬ

                        \ MYMEMORY moves with HERE. be aware.

MYMEMORY HEX 1000 ERASE\заполните его 2 Кбайтами нуля

Forth обычно используется для высокопроизводительных встроенных приложений, где распределение динамической памяти может вызывать ненадежный код, поэтому предпочтение отдается статическому распределению с использованием ALLOT. Однако большие системы имеют кучу и используют ALLOCATE, FREE AND RESIZE так же, как мы используем malloc и т.д. В C.

BF

Ответ 3

Питер Мортенсен очень хорошо объяснил это. Я добавлю несколько заметок, которые могут помочь программисту C.

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

Словарь лучше всего рассматривать как "статические данные" с точки зрения программирования C. Вы можете зарезервировать диапазоны адресов в словаре, но в целом вы будете использовать ALLOT и связанные слова для создания статических структур данных и пулов, которые не меняют размер после выделения. Если вы хотите реализовать связанный список, который может расти в реальном времени, вы можете использовать достаточное пространство для ячеек ссылок, которые вам понадобятся, и писать слова, чтобы поддерживать свободный список ячеек, из которых вы можете рисовать. Есть естественные реализации такого рода вещей, и писать свои собственные - это хороший способ оттачивать навыки управления указателями.

Распределение кучи доступно во многих современных Forths, и стандарт определяет слова ALLOCATE, FREE и RESIZE, которые работают как malloc(), free() и realloc() в C. Память, которую они возвращают, из кучи операционной системы, и обычно полезно сохранить адрес в переменной или какой-либо другой более постоянной структуре, чем стек, чтобы вы случайно не потеряли указатель, прежде чем сможете его освободить. В качестве побочного примечания эти слова (вместе с словами ввода/вывода файла) возвращают статус в стеке, который не равен нулю, если произошла ошибка. Это соглашение прекрасно сочетается с механизмом обработки исключений и позволяет писать код типа:

variable PTR
1024 allocate throw PTR !
\ do some stuff with PTR
PTR @ free throw
0 PTR !

Или для более сложного, если несколько искусственного примера allocate/free:

\ A simple 2-cell linked list implementation using allocate and free
: >link ( a -- a ) ;
: >data ( a -- a ) cell + ;
: newcons ( a -- a )    \ make a cons cell that links to the input
   2 cells allocate throw  tuck >link ! ;
: linkcons ( a -- a )   \ make a cons cell that gets linked by the input
   0 newcons dup rot >link ! ;
: makelist ( n -- a )   \ returns the head of a list of the numbers from 0..n
   0 newcons  dup >r
   over 0 ?do
     i over >data ! linkcons ( a -- a )
   loop  >data !  r> ;
: walklist ( a -- )
   begin   dup >data ?  >link @           dup 0= until drop ;
: freelist ( a -- )
   begin   dup >link @  swap free throw   dup 0= until drop ;
: unittest  10 makelist dup walklist freelist ;

Ответ 4

Некоторые реализации Forth поддерживают локальные переменные в кадре стека возврата и выделения блоков памяти. Например, в SP-Forth:

lib/ext/locals.f
lib/ext/uppercase.f

100 CONSTANT /buf

: test ( c-addr u -- ) { \ len [ /buf 1 CHARS + ] buf }
  buf SWAP /buf UMIN DUP TO len CMOVE
  buf len UPPERCASE
  0 buf len + C! \ just for illustration
  buf len TYPE
;

S" abc" test \ --> "ABC"

Ответ 5

С Forth вы входите в другой мир.

В типичном Forth, таком как ciforth на linux (и предполагая 64 бита), вы можете настроить свой Forth на линейное пространство памяти, размер которого равен вашему размеру подкачки (например, 128 Гбайт). Это ваше, чтобы заполнить массивами, связанными списками, фотографиями. Нет никаких ограничений. Forth предоставляет только указатель HERE, который поможет вам отслеживать память, которую вы израсходовали. Даже если вы можете игнорировать, и в стандарте 1994 года есть даже слово, которое обеспечивает свободное пространство, которое плавает в свободной памяти (PAD).

Есть ли что-то вроде malloc() free()? Не обязательно в небольшом ядре пары десятков килобайт. Но вы можете просто добавить файл с утилитой allocate и выделить пару Гбайт для использования в динамической памяти.

В качестве примера я сейчас работаю с файлами tiff. Типичный 140-мегабайтный снимок выводит небольшой фрагмент из словаря, продвигающегося ЗДЕСЬ. Строки пикселей преобразуются, распаковываются и т.д. Для этого я использую динамическую память, поэтому я использую пробел для результата декомпрессии строки. Я должен вручную БЕСПЛАТНО их снова, когда результаты были использованы для другого преобразования. Он чувствует себя совершенно иначе, чем в. Существует больше контроля и больше опасности.

Ваш вопрос о областях и т.д. В Forth, если вы знаете адрес, вы можете получить доступ к структуре данных. Даже если вы записали F7FFA1003 на листе бумаги. Попытка сделать программы более безопасными по отдельным пространствам имен не видна в стиле Форт. Так называемый список слов (см. Также VOCABULARY) предоставляет средства в этом направлении.