Выделение и освобождение динамической памяти
Вся динамическая память в Турбо Паскале рассматривается как сплошной массив байтов, который называется кучей. Физически куча располагается в старших адресах сразу за областью памяти, которую занимает тело программы.
Начало кучи хранится в стандартной переменной HEAPORG (рис. 6.3), конец – в временной HEAPEND. Текущую границу незанятой динамической памяти указывает указатель HEAPPTR.
Память под любую динамически размещаемую переменную выделяется процедурой NEW. Параметром обращения к этой процедуре является типизированный указатель. В результате обращения указатель приобретает значение, соответствующее динамическому адресу, начиная с которого можно разместить данные, например:
var i, j: Integer; r: Real; begin New(i); ……. end.
После выполнения этого фрагмента указатель / приобретет значение, которое перед этим имел указатель кучи HEAPPTR, а сам HEAPPTR увеличит свое значение на 2, так как длина внутреннего представления типа INTEGER, с которым связан указатель I, составляет 2 байта (на самом деле это не совсем так: память под любую переменную выделяется порциями, кратными 8 байтам – см. п.6.7). Оператор:
new(r);
Вызовет еще раз смещение указателя HEAPPTR, но теперь уже на 6 байт, потому что такова длина внутреннего представления типа REAL. Аналогичным образом выделяется память и для переменной любого другого типа.
Рис. 6.3. Расположение кучи в памяти ПК
После того как указатель приобрел некоторое значение, т.е. стал указывать на конкретный физический байт памяти, по этому адресу можно разместить любое значение соответствующего типа. Для этого сразу за указателем без каких-либо пробелов ставится значок ^, например:
i: = 2; {B область памяти i помещено значение 2} r: = 2*pi; {В область памяти r помещено значение 6.28}
Таким образом, значение, на которое указывает указатель, т.е. собственно данные, размещенные в куче, обозначаются значком ^, который ставится сразу за указателем. Если за указателем нет значка ^, то имеется в виду адрес, по которому размещены данные. Имеет смысл еще раз задуматься над только что сказанным: значением любого указателя является адрес, а чтобы указать, что речь идет не об адресе, а о тех данных, которые размещены по этому адресу, за указателем ставится π. Если Вы четко уясните себе это, у Вас не будет проблем при работе с динамической памятью.
Динамически размещенные данные можно использовать в любом месте программы, где это допустимо для констант и переменных соответствующего типа, например:
r: = sqr(r) + i -17;
Разумеется, совершенно недопустим оператор:
r: = sqr(r) + i -17;