TURBO PASCAL |
Новости
|
Методы освобождения областей динамически распределяемой памятиДинамические переменные, сохраняемые в динамически распреде- ляемой области, освобождаются одним из двух следующих способов: 1. С помощью процедур Dispose или FrееМем. 2. С помощью процедур Маrk и Rеlеаsе. Простейшей схемой использования процедур Маrk и Rеlеаsе, например, является выполнение следующих операторов: New(Ptr1); New(Ptr2); Mark(P); New(Ptr3); New(Ptr4); New(Ptr5); Схема динамически распределяемой области при этом будет выг- лядеть, как показано на Рис. 21.2. HeapEnd ──>┌──────────────────────────┐ Верхняя граница │ │ памяти │ │ HeapPtr ──>├──────────────────────────┤ │ содержимое Ptr5^ │ Ptr5 ──>├──────────────────────────┤ │ содержимое Ptr4^ │ Ptr4 ──>├──────────────────────────┤ │ содержимое Ptr3^ │ Ptr3 ──>├──────────────────────────┤ │ содержимое Ptr2^ │ Ptr2 ──>├──────────────────────────┤ │ содержимое Ptr1^ │ Ptr1 ──>└──────────────────────────┘ Нижняя граница памяти Рис. 21.2 Метод освобождения областей динамически распреде- ляемой области помощью процедур Маrk и Rеlеаsе. Оператор Маrk(P) отмечает состояние динамически распределяе- мой области непосредственно перед выделением памяти для перемен- ной Ptr3 (путем сохранения текущего значения переменной НеаpPtr в P). Если выполняется оператор Rеleаsе(P), то схема динамически распределяемой области становится такой, как показано на Рис. 21.3. При этом, поскольку производится обращение к процедуре Маrk, освобождается память, выделенная под все указатели. Примечание: Выполнение процедуры Rеleаsе(НеаpОrg) пол- ностью освобождает динамически распределяемую область памя- ти, поскольку переменная НеаpOrg указывает на нижнюю грани- цу динамически распределяемой области. HeapEnd ──>┌──────────────────────────┐ Верхняя граница │ │ памяти │ │ │ │ │ │ │ │ │ │ HeapPtr ──>├──────────────────────────┤ │ содержимое Ptr2^ │ Ptr2 ──>├──────────────────────────┤ │ содержимое Ptr1^ │ Ptr1 ──>└──────────────────────────┘ Нижняя граница памяти Рис. 21.3 Схема динамически распределяемой области при вы- полнении процедуры Rеleаsе(P). Применение процедур Маrk и Rеlеаsе для освобождения памяти, выделенной для динамических переменных, на которые ссылаются ука- затели, выполняемое в порядке, в точности обратном порядку выде- ления памяти, весьма эффективно. Однако в большинстве программ имеется тенденция в более случайному выделению и освобождению па- мяти, отведенной для динамических переменных, на которые ссылают- ся указатели, что влечет за собой необходимость использования бо- лее тонких методов управления памятью, которые реализованы с по- мощью процедур Dispose и FrееMem. Эти процедуры позволяют в любой момент освободить память, выделенную для любой динамической пере- менной, на которую ссылается указатель. Когда с помощью процедур Dispose и FrееМем освобождается па- мять, отведенная для динамической переменной, не являющаяся "са- мой верхней" переменной в динамически распределяемой области, то динамически распределяемая область становится фрагментированной. Предположим, что выполнялась та же последовательности операторов, что и в предыдущем примере. Тогда после выполнения процедуры Dispose(Ptr3) в центре динамически распределяемой области памяти образуется незанятое пространство ("дыра"). Это показано на Рис. 21.4. HeapEnd ──>┌──────────────────────────┐ Верхняя граница │ │ памяти │ │ HeapPtr ──>├──────────────────────────┤ │ содержимое Ptr5^ │ Ptr5 ──>├──────────────────────────┤ │ содержимое Ptr4^ │ Ptr4 ──>├──────────────────────────┤ │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ ├──────────────────────────┤ │ содержимое Ptr2^ │ Ptr2 ──>├──────────────────────────┤ │ содержимое Ptr1^ │ Ptr1 ──>└──────────────────────────┘ Нижняя граница памяти Рис. 21.4 Создание незанятой области ("дыры") в динамически распределяемой области памяти. Если в данный момент выполняется процедура New(Ptr3), то это опять приведет к выделению той же области памяти. С другой сторо- ны, выполнение процедуры Dispose(Ptr4) увеличит размер свободного блока, так как Ptr3 и Ptr4 были соседними блоками (см. Рис. 21.5). HeapEnd ──>┌──────────────────────────┐ Верхняя граница │ │ памяти │ │ HeapPtr ──>├──────────────────────────┤ │ содержимое Ptr5^ │ Ptr5 ──>├──────────────────────────┤ │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ ├──────────────────────────┤ │ содержимое Ptr2^ │ Ptr2 ──>├──────────────────────────┤ │ содержимое Ptr1^ │ Ptr1 ──>└──────────────────────────┘ Нижняя граница памяти Рис. 21.5 Увеличение размера незанятого блока памяти. В конечном итоге выполнение процедуры Dispose(Ptr5) приведет сначала к созданию незанятого блока большего размера, а затем НеаpPtr переместится в более младшие адреса памяти. Поскольку последним допустимым указателем теперь будет Ptr2 (см. Рис. 21 6), то это приведет к действительному освобождению незанятого блока. HeapEnd ──>┌──────────────────────────┐ Верхняя граница │ │ памяти B.Pascal 7 & Objects/LR - 355 - │ │ │ │ │ │ │ │ │ │ │ │ │ │ HeapPtr ──>├──────────────────────────┤ │ содержимое Ptr2^ │ Ptr2 ──>├──────────────────────────┤ │ содержимое Ptr1^ │ Ptr1 ──>└──────────────────────────┘ Нижняя граница памяти Рис. 21.7 Освобождение незанятого блока памяти. Как показано на Рис. 21.7, динамически распределяемая об- ласть памяти теперь находится в том же самом состоянии, в каком она находилась бы после выполнения процедуры Rеlеаsе(P). Однако создаваемые и освобождаемые при таком процессе незанятые блоки отслеживаются для их возможного повторного использования. |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |