TURBO PASCAL |
Новости
|
Выделение и освобождение динамической памятиВся динамическая память в Турбо - Паскале рассматривается как сплошной массив байтов, который называется кучей. Физически куча располагается в старших адресах сразу за областью памяти, которую занимает тело программы:
END. После выполнения процедуры NEW(I) указатель ] приобретает значения, которые имел указатель кучи HEAPPTR, а сам HEAPPTR увеличивает свое значение на величину памяти, выделяемой для переменной, на адрес которой указывает указатель I. Память под любую переменную выделяется порциями, кратными 8 байт. Для доступа к переменной, адрес которой содержит указатель имеются две возможности: 1 - Использовать идентификатор переменной 2- Использовать адрес переменной, который содержит указатель. Первый способ нам известен: мы его использовали раньше. Во втором способе используется разименование указателя: для того, чтобы по указателю на переменную получить доступ к самой переменной нужно после переменной - указателя поставить символ А. Например: 1Л:=2 - в область памяти I помещено значение 2 RA:=2*PI - в область памяти R помещено значение 6.28 Разименование считается некорректным, если переменная - указатель имеет значение NIL; то есть не существует переменной, на которую ссылается такой указатель. Нетипизированные указатели не могут быть разименованы обычным образом (т. е. как типизированные указатели: 1Л:=2), но могут разименовываться для вычисления адреса (см. раздел "Пример использования большого массива данных" ). Динамически размещенные данные можно использовать в любом месте программы, где это допустимо для констант и переменных соответствующего типа, например: RA:=SQRT(RA)+IM7 но: R:=SQRT(RA)+IA-17 - недопустимо, так как нельзя присваивать указателю вещественное значение R:=SQRT(R) - недопустимо, таг как нельзя значение указателя возводить в квадрат. RA:=I - недопустимо, так ках нельзя вещественным данным, на которые указывает указатель, присвоить значение указателя. Как было сказано выше, над указателями разрешены только следующие операции: присваивание и сравнение (=,о). При этом необходимо учитывать соответствие типов: в этих операциях гипы переменных, а также 'типы значений должны быть либо одинаковыми либо совместимыми. Для возврата динамической пампк назад в кучу используется процедура DISPOSE(P) , где Р * типизированный указатель. Для нашего примера D1SPOSE(R) и DISPOSER) вернут в кучу тот объем памяти, который был выделен под переменные R Hi. Процедура DISPOSE(PTR) не изменяет значение указателя PTR, а лишь возвращает в кучу память, ранее связанную с этим указателем. Однако повторное применение процедуры к свободному указателю приведет к возникновению ошибки периода исполнения. Освободившему» указателю можно присвоить константу NIL (пометить его этой константой) для того, чтобы в дальнейшем определить такой свободный адрес по этой пометке: CONST 1 P:AREAL=NIL:j BEGIN IF P=NIL THEN NEW(P); DISPOSE(P); P:=NIL; END. Начальное значение указателя пру. объявлении его в разделе переменных может быть произвольным Поэтому более предпочтительный способ объявления указателя -в виде типизированной константы с одновременным присвоением ему значения NIL. Чередование обращений к процедурам NEW и DISPOSE обычно приводит к образованию ячеистой структуры памяти. При очередном обращении к NEW отыскивается наименьший свободный фрагмент, в который может поместиться требуемая переменная. Адрес начала найденного фрагмента помещается в указатель, а сам фрагмент или его часть нужной длижы помечается как занятая часть кучи. Выделением, освобождением и учетом динамической памяти занимается специальная программа - администратор кучи. Освобождение целого фрагмента кучи: VAR P1,P2,P3,P4,P5,: INTEGER; BEGIN NE\V(P1) NEW(P2) MARK(P); NEW(P3); NEW(P4); NEW(P5); RELEASE(P) или DISPOSE(P3) END. Процедура MARK(P) присваивает переменной - указателю Р текущее значение указателя HEAPPTR. Процедура RELEASE(?) освобождает динамическую память начиная от адреса в указателе Р и до конца кучи: Старшие адреса Состояние динамической памяти: a) перед освобождением b) после Dispose(p3) c) после Release(p) Для резервирования и освобождения динамической памяти при использовании нетипизированных указателей применяются процедуры: GETMEM(P,SIZE) - для резервирования FREEMEM(P,SIZE) - для освобождения, где: Р- нетипизированный указатель SIZE - размер в байтах части кучи Данный процедуры работают аналогично процедурам NEW(P) и DISPOSE(P). За одно обращение к процедуре GETMEM(P,SIZE) можно зарезервировать не более 65521 байт динамической памяти. Использование процедур GETMEM(P,SIZE) и FREEMEM(P,SIZE) как и вообще работа с динамической памятью требует особой осторожности и тщательного соблюдения правила: освобождать нужно ровно столько памяти, сколько ее было зарезервировано, и именно с того адреса, с которого она была зарезервирована. Использование нетипизированных указателей позволяет осуществлять неявное преобразование типов: по одному адресу можно размешать различные типы данных лишь бы они занимали одинаковый объем памяти. |
На первую страницу
(с)Все права защищеныПо всем интересующим вопросам прошу писать на электронный адрес |