Читайте также:
|
|
Вся динамической памяти в Turbo Pascal представляет собой сплошной массив байтов, называемый кучей. Физически куча располагает за областью память, которую занимает тело программы.
Начало кучи храниться в стандартной переменной heaporg, конец – в переменной heapend. Текущая граница незанятой динамической памяти храниться в указатели heapptr.
Память под любую динамическую переменную выделяется процедурой new, параметром обращения к которой является типизированный указатель. В результате обращения последний принимает значение, соответствующее динамическому адресу начиная с которого можно разметить данные.
Пример:
Var
i,j:^integer;
R:^real;
Begin
New(i);
New (r);
New (j);
В результате обращения первого оператора указатель i принимает значение, которое перед этим имел указатель кучи heapprt. Сам heapprt увеличивает свое значение на два, так как длина внутреннего представления типа integer, связанного с указателем I, составляет 2 байта. Оператор New (r); вызывает еще одно смещение указателя heapprt, но уже на 6 байт, потому что такова длина внутреннего представления типа real. Аналогичная процедура применяется и для переменной любого другого типа. После того как указатель стал определить конкретный физический байт памяти, по этому адресу можно разместить любое значение соответствующего типа, для чего сразу за указателем без каких либо пробелов ставиться значок ^.
Таким образом, значение, которое определяет указатель, то есть собственно данные, размещенные в куче, обозначаются значком ^, который ставиться за указателем. Если за последним этот значок отсутствует, то имеется в виду адрес, по которому размещаются данные. Динамически размещенные данные (но не их адрес!) можно использовать для констант и переменных соответствующего типа в любом месте, где это доступно.
Пример:
r^:=sgr(r^)+sin(r^+i^)-2.3;
Невозможен оператор
r:= sgr(r)+i^;
так как указателю r нельзя присвоить значение вещественного типа. Точно также недопустим оператор
r^:= sgr(r);
поскольку значением указателя r является адрес, и его (в отличие от того значения, которое размещено по данному адресу) нельзя возводить в квадрат. Ошибочным будет и присвоение r^:= i; так как вещественным данным, на которое указывает r^, нельзя давать значение указателя (адрес). Динамическую память можно не только забирать из кучи, но и возвращать обратно. Для этого используется процедура dispose(p), где р –указатель, который не изменяет значение указателя, а лишь возвращает в кучу память, ранее связанную с указателем.
При работе с указателями и динамической памятью необходимо самостоятельно следить за правильность использования процедур new, dispose и работы с адресами и динамическими переменными, так как транслятор такие ошибки не контролируются. Ошибки этого класса могут не только привести к зависанию компьютера, но и иметь более серьезные последствия.
Другая возможность состоит в освобождении целого фрагмента кучи. С этой целью перед началом выделения динамической памяти текущее значение указателя heapptr запоминается в переменой-указателе с помощью процедуры mark. Теперь можно в любой момент освободить фрагмент кучи, начиная с того адреса, который запомнила процедура mark, и до конца динамической памяти. Для этого используется процедура release.
Процедура mark запоминает текущее указание кучи heapptr (обращение mark(ptr), где ptr – указатель любого типа, в котором будет возвращено текущее значение heapprt). Процедура release(ptr), где ptr – указатель любого типа, освобождает участок кучи от адреса, хранящегося в указателе до конца кучи.
Дата добавления: 2015-02-16; просмотров: 85 | Поможем написать вашу работу | Нарушение авторских прав |