Читайте также:
|
|
Длина сегмента определяется архитектурой процессора 8086 и составляет 64 Килобайта (65536 байт), что может вызвать определённые трудности при описании и обработке больших массивов данных. С другой стороны объём стандартной памяти - 640 Килобайт. Выход - использовать динамическую память.
Динамическая память - это оперативная память ЭВМ, предоставляемая Турбо-Паскалевой программе при её работе, за вычетом сегмента данных (64 К), стека (обычно 16 К) и собственно тела программы. По умолчанию размер динамической памяти определяется всей доступной памятью ЭВМ и, как правило, составляет не менее 200 - 300 Кбай
Динамические переменные - размещаются в памяти непосредственно в процессе работы программы. При динамическом размещении заранее неизвестны ни тип, ни количество размещаемых данных, к ним нельзя обращаться по именам, как к статическим переменным
Указатель - это переменная, которая в хранит качестве своего значения адрес байта памяти.
В 8086 адреса задаются совокупностью двух шестнадцатиразрядных слов - сегмента и
смещения. Сегмент - участок памяти, имеющий максимальную длину 64 К и начинающийся к физического адреса, кратного 16 (то есть 0, 16, 32, 48 и т.д.). Смещение - указывает, сколько байт от начала сегмента нужно пропустить, чтобы обратиться по нужному адресу. Фрагмент памяти в 16 байт называется параграфом. Сегмент адресует память с точностью до параграфа, а смещение - с точностью до байта.
Указатель адресует лишь первый байт типа данных.Процессор 8086 всегда генерирует 20-ти бытовые адреса за счёт добавления 16-ти битового смещения к содержимому регистра, умноженному на 16:
физический адрес = смещение + 16 * регистр сегмента.
так как динамическая память позволяет использовать организацию данных в виде списков (каждый элемент имеет в своём составе ссылку на соседний элемент - обратите внимание на поле Next).
В Турбо-Паскале можно объявлять указатель и не связывать его с конкретным типом данных:
Var
PP: Pointer;
Указатели такого рода называют нетипизированными. В них удобно размещать данные, структура которых меняется по ходу работы.
В Турбо-Паскале можно передавать значения только между указателями, связанными с одним и тем же типом данных.
Выделение и освобождение динамической памяти Вся динамическая память – пространство ячеек, называемое кучей. Физически куча располагается в старших адресах, сразу за программой. Указатель на начало кучи храниться в предопределенной переменной HeapOrg, конец - FreePtr, текущую границу незанятой динамической памяти указывает указатель HeapPtr. Для выделения памяти под любую переменную используется процедура New. Единственным параметром является типизированный указатель:
Var
I,J: ^Integer;
R: ^Real;
Begin
New(I); {под I выделяется область памяти,}
{адрес первого байта этой области помещается в I}
End.
После выполнения этого фрагмента указатель I приобретёт значение, которое перед этим имел указатель кучи HeapPtr, а HeapPtr увеличится на два (т.к. он типа Integer); New(R) - вызовет смещение указателя на 6 байт. После того как указатель приобрёл некоторое значение, то есть стал указывать на конкретный байт памяти, по этому адресу можно разместить значения соответствующего типа:
I^:= 2;
R^:= 2*Pi;
Допустима запись: R^:= Sqr (R^) + I^ - 17;
Но недопустима запись: R:= Sqr (R^) + I^ - 17; так как указателю R нельзя присвоить значение вещественного выражения.
Возврат динамической памяти обратно в кучу осуществляется оператором Dispose:
Dispose(R);
Dispose(I); - вернут в кучу, ранее забранные 8 байт.
Использование указателей, которым не присвоено значение процедурой New или каким-либо другим способом, никак не контролируется системой и может привести к непредсказуемым результатам. Многократное чередование New и Dispose приводит к “ячеистой” структуре кучи. Дело в том, что все операции с кучей выполняется под управлением особой программы, которая ведёт учёт всех свободных фрагментов в куче. При выполнении оператора New() эта программа отыскивает минимальный свободный фрагмент, в котором может разместиться требуемая переменная. Адрес начала найденного фрагмента возвращается в указателе, а сам фрагмент или его часть нужной длины, помечаются как занятая часть кучи.
Можно освободить целый фрагмент кучи следующим образом:
1. Перед началом выделения динамической памяти значения указателя HeapPtr запоминается в переменной-указателе с помощью процедуры Mark.
2. Выполнение программы.
3. Освобождение фрагмента кучи от заполненного адреса до конца динамической памяти с использованием процедуры Release.
Var
P, P1, P2, P3, P4, P5: ^Integer;
Begin
New(P1);
New(P2);
New(P3);
New(P4);
New(P5);
Mark(P);
........
Release (P);
End.
В этом примере процедурой Mark(P) в указатель P было помещено текущее значение HeapPtr, однако память под переменную не резервировалась.
Для работы с нетипизированными указателями используются также процедуры GetMem(P, Size) иFreeMem(P, Size) - резервирование и освобождение памяти.
P - нетипизированный указатель, Size - размер.
За одно обращение к куче процедурой GetMem можно зарезервировать до 65521 байт. Освобождать нужно ровно столько памяти, сколько было зарезервировано, и именно с того адреса, с которого память была зарезервирована, иначе программа не будет работать и завершаться корректно!!!
смысла}
Дата добавления: 2015-02-22; просмотров: 98 | Поможем написать вашу работу | Нарушение авторских прав |