После объявления в программе ссылки или указателя его значение не определено и содержит случайный адрес. Для работы с динамическими переменными их всегда необходимо сначала разместить специальными процедурами в памяти или хотя бы присвоить ссылке корректное значение адреса.
11.3. Организация памяти области кучи
Для размещения динамических переменных используется область памяти, называемая «кучей». Место для данных в куче
- 198 -
отводится и освобождается только во время работы программы, и именно поэтому мы говорим о динамических данных. Место для прочих переменных отводится в специальном сегменте данных еще на этапе компиляции и не меняется впоследствии — это статические данные. Интересно, что сами ссылочные переменные являются статическими и располагаются в сегменте данных, но данные на которые они впоследствии ссылаются, как правило, организуются в куче.
На рис. 11.3 представлено распределение памяти области кучи при работе программ, написанных на Турбо Паскале. Куча первоначально всегда свободна и заполняется от нижних адресов в области кучи. Эта область характеризуется двумя предопределенными в языке указателями (переменными типа Pointer): HeapOrg и HeapPtr. Переменная HeapOrg указывает на начало кучи. Как видно из рис. 11.3, куча начинается сразу за оверлейным буфером. Если же программа не имеет оверлейных блоков, то куча начинается сразу за областью стека. Значение HeapOrg постоянно и, как правило, не меняется по ходу выполнения программы.
Переменная HeapPtr указывает на нижнюю границу свободного пространства в куче. Каждый раз, когда в куче размещается наверху новая динамическая переменная, этот указатель перемещается на размер переменной. При этом он нормализуется (приводится к виду СЕГМЕНТ:СМЕЩЕНИЕ) таким образом, что смещение находится в диапазоне от 0 до $F (15). Максимальный размер переменной, которая может быть размещена в куче равен 65520 байт, так как каждая переменная должна находится в одном сегменте и «оставлять» в нем 15 байтов.
Верхняя граница памяти MS-DOS
Рис. 11.3
- 199 -
Переменные HeapOrg и HeapPtr не стоит использовать в программах, пока не требуется распределять память кучи лучше, чем системные процедуры Турбо Паскаля. Но для опытных программистов, собирающихся производить «уборку мусора» и оптимизацию кучи, они могут быть полезны.
11.4. Управление размерами области кучи и стека
Программа на Турбо Паскале может сама определять размеры необходимой памяти для динамических переменных и локальных параметров процедур и функций. Так, можно задать размер стека и два параметра кучи. Эти значения устанавливаются с помощью директивы компилятора
{$М Стек, МинимумКучи, МаксимумКучи }
при компиляции программы. Эта директива должна быть в первых строках основной программы (в модулях она игнорируется). При указании размеров кучи в директиве {$М...} помните, что программа не будет выполняться, если свободной памяти, оставшейся после загрузки выполнимого файла, будет меньше, чем задано минимальным (нижним) значением МинимумКучи. Всегда должно выполняться условие
МинимумКучи <= МаксимумКучи.
Диапазон значений области стека — от 1024 до 65535 байт (1К...64К), а обоих параметров кучи — от 0 до 655360 байт (0...640К). Максимальное значение объема кучи может быть больше, чем объем реально свободной памяти. В таком случае кучей будет использоваться вся свободная память.
Если директива {$М...} не указана, то значения минимального (нижнего) и максимального (верхнего) размеров кучи устанавливаются равными 0 и 655360 соответственно. Это означает, что под кучу будет использоваться вся оставшаяся в ПЭВМ свободная память.
Можно установить эти параметры в среде программирования, используя меню Options/Compiler/Memory.
Реальная необходимость в явном задании размеров стека и памяти возникает лишь при запуске субпроцессов и организации резидентных программ.
11.5. Процедуры управления кучей
Управление кучей осуществляет монитор кучи, являющийся частью системной библиотеки Турбо Паскаля. Он реализует следу-
- 200 -
ющие процедуры и функции (табл. 11.1), размещающие и удаляющие динамические переменные из кучи и анализирующие ее состояние.
Таблица 11.1