28636

Динамическая память и указатели

Лекция

Информатика, кибернетика и программирование

Все рассмотренные ранее типы данных (кроме типа file) представляли статические структуры. Память выделялась под переменные этих типов до выполнения программы, а размер выделяемой памяти определялся по описаниям соответствующих переменных (например, для переменной типа byte выделялся 1 байт оперативной памяти). Такая память является статической, поскольку её размер не может изменяться при выполнении программы.

Русский

2013-08-20

54 KB

28 чел.

Лекция 23: Динамическая память и указатели.

1. Статическая и динамическая память.

2. Управление динамической памятью.

3. Тип данных - Указатель.

4. Принципы работы с указателями.

1. Статическая и динамическая память.

Все рассмотренные ранее типы данных (кроме типа file) представляли статические структуры. Память выделялась под переменные этих типов до выполнения программы, а размер выделяемой памяти определялся по описаниям соответствующих переменных (например, для переменной типа byte выделялся 1 байт оперативной памяти). Такая память является статической, поскольку её размер не может изменяться при выполнении программы.

Статическая оперативная память в системе Турбо Паскаль выделяется программе отдельным сегментом, размер которого составляет 64 Кбайт. Статическая память освобождается при завершении программы. Такой принцип распределения оперативной памяти представляет серьёзные ограничения для программирования многих задач. Для ряда задач это ограничение столь серьёзно, что делает невозможным решение этих задач. Преодолеть недостатки статической памяти можно использованием динамической памяти.

Динамическая память способна полностью использовать физический объём оперативной памяти, имеющийся на компьютере. Особенность динамической памяти состоит в том, что она выделяется и освобождается в процессе выполнения программы по запросам самой программы. Динамическая память часто используется в программах Турбо Паскаля, решающих задачи управления, проектирования, обучения, а также игровые задачи. Без неё практически не обходится ни одна прикладная программа на Турбо Паскале, поэтому работа с динамической памятью является важнейшей в арсенале средств прикладного программиста.

2. Управление динамической памятью.

Для организации динамической памяти в Турбо Паскале предусмотрен специальный механизм, реализованный обслуживающей программой - менеджером динамической памяти. Вся динамическая память рассматривается менеджером как сплошной массив байтов, называемый хип-памятью (heap). Физическая хип-память размещается в старших адресах сразу за областью памяти, отводимой под тело программы. Рис. 3 иллюстрирует принцип организации хип-памяти:

     Направление возрастания адресов

0                       max                      

Системная область

Программа

   Динамическая

память

Cистемная область

                                                                                          

                    HeapOrg              HeapPtr        HeapEnd         

    

Рис. 3.  Организация динамической памяти в Турбо Паскале.

HeapOrg- начало хип-памяти,

HeapPtr-  текущая граница свободной хип-памяти,

HeapEnd- конец хип-памяти.

Указатель границы занятой памяти HeapPtr отслеживает запросы программы на выделение динамической памяти под динамически размещаемые переменные и может сдвигаться вправо при каждом обслуженном запросе (величина сдвига зависит от типа динамически размещаемой переменной). На рис.3 левая штриховка хип-памяти соответствует занятой области памяти (по обслуженным запросам), а правая штриховка - незанятой (свободной) хип-памяти. Хип-память выделяется порциями, кратными 8 байтам. При освобождении хип-памяти она возвращается для последующего возможного выделения по очередным запросам. Менеджер хип-памяти ведёт учёт всех свободных фрагментов хип-памяти, организуя их в список свободных фрагментов, расположенных ниже границы HeapPtr. При запросе на выделение хип-памятиꗬÁIЙለ¿ကЀሢ橢橢뎲뎲Й鈰
ጕƓ￿￿￿]۸۸۸۸ૌૌૌૠૠૠૠ8ଘʹຌΌૠꀴìᓤŬᙐᙦᙦᙦ嚑ଈ憙̴操Ɯ锜锞锞锞5镓Ô阧Ô電ꄠǴ
f電हૌ晩嘕|嚑晩晩電ся хип-памяти во многом случайны и зависят от динамики работы программы, может наблюдаться фрагментация структуры хип-памяти, при которой занятые и свободные участки памяти чередуются случайным образом. Менеджер придерживается также некоторой стратегии, позволяющей рационально распределять хип-память (мы не останавливаемся на этой проблеме более подробно).

3. Тип данных - Указатель.

Для работы с динамической памятью в Турбо Паскале используется специальный тип данных - Указатель. Переменная типа Указатель имеет значением адрес оперативной памяти. Адрес приписан каждому байту оперативной памяти (от 0 до max) и состоит из двух частей: сегмента и смещения. Сегмент - непрерывный участок оперативной памяти длиной 64кбайт, начинающийся с физического адреса, кратного 16. Смещение указывает относительный адрес внутри сегмента. Как сегмент, так и смещение являются данными типа word. Таким образом, по своей внутренней структуре указатель состоит из двух слов типа word. С помощью указателя можно размещать в хип-памяти любой тип данных Турбо Паскаля (кроме файла). В случае, когда размещаемый тип данных имеет длину более 1 байта, указатель указывает на начало соответствующей структуры (на первый байт данных).

В Турбо-Паскале имеется два вида указателей:

типизированный указатель, указывающий на заданный тип данных;

нетипизированный указатель, указывающий лишь на область памяти данных.

Форма описания указателя зависит от вида указателя. Типизированный указатель описывается в следующей синтаксической форме:

type <имя типа-указателя> = ^ <имя базового типа >;

Здесь базовым типом может быть любой тип Турбо Паскаля, а символ ^, помещаемый перед базовым типом, идентифицирует тип-указатель.

Например: type pint = ^integer; - тип-указатель на данные типа integer.

Синтаксическая форма описания нетипизированного указателя имеет вид:

type <имя типа-указателя> =pointer;

Для работы с указателями, как и с любыми другими типами данных, объявляются переменные типа-указатель.

Например: var pp:pint; { переменная типа pint (типизированный указатель)}

    np:pointer;  {переменная нетипизированного указателя}

Наиболее часто указатели используются для создания рекурсивных структур, характерным примером которых являются списки.

Рекурсивной называется структура, описание которой содержит обращение к самой себе. Такие обращения в Турбо Паскале возможно реализовать только с помощью указателей.

Например: type refer = ^ inf; inf = record name,adr,tel:string;next:refer end;

Эта рекурсивная структура описывает линейный список, элементами которого являются записи, содержащие информацию о телефонах (три поля: имя, адрес и номер телефона) и указатель на следующую запись в списке.

4. Принципы работы с указателями.

Переменная типа указатель, как мы установили выше, всегда является некоторым адресом оперативной памяти, идентифицирующим размещаемую в хип-памяти структуру данных.

Создание указателя на структуру, по сути, является особым способом именования этой структуры, отличным от имён, принятых для статических переменных. Необходимо помнить, что обращаясь к указателю, мы обращаемся не непосредственно к структуре данных (не к её значению !), а лишь к адресу начала размещения этой структуры.

В тех случаях, когда необходимо обратиться к значению представленной структуры данных, следует выполнить операцию разыменования, которая в Турбо Паскале имеет специальное обозначение: если p - указатель, то p^ - значение, на которое указывает p. (Обратите внимание, что символ ^ при разыменовании записывается после переменной-указателя, а не до него, как  при описании типизированного указателя).

Над указателями (т.е. адресами) допустимы операторы присваивания вида:

p1:=p2; - где p1,p2 - только указатели одного и того же типа.

p:= nil; -  где р - переменная типа указатель, а nil - нулевой указатель (не являющийся ни одним из адресов хип-памяти), т.е. "нулевая" константа типа указатель.

Для работы с указателями в Турбо Паскале предусмотрен ряд стандартных процедур и функций. Важнейшими из них являются процедуры выделения (резервирования)  хип-памяти под структуры, на которые указывают указатели.

Выделение хип-памяти под структуры, именуемые типизированными указателями, выполняет следующая процедура:   

new(<переменная типизированного указателя>);

При выполнении этой процедуры менеджер выделяет хип-память для размещения структуры, на которую указывает параметр этой процедуры. Значением этого параметра становится адрес, на котором начинается указанная структура. Заметим, что непосредственно после выполнения new значение размещаемой структуры неопределенное - просто под структуру зарезервирована память. Для "наполнения" этой структуры каким-либо значением можно использовать присваивание разыменованному указателю.

Для нетипизированных указателей память выделяется  другой процедурой:

getmem(<нетипизированный указатель>, < размер памяти >);

где: <размер памяти> указывается в байтах.

Действие процедуры getmem аналогично процедуре new, различие лишь в том, что размер структуры задаётся явно вторым параметром этой процедуры (для new он определялся неявно по описанию типа указателя).

Заметим, что работа с нетипизированными указателями сложнее, т.к. всю ответственность за размещение структуры и её "наполнение" значением несёт только сам программист. В то же время этот вид указателей обладает большей гибкостью и способен размещать в одном и том же фрагменте памяти различные типы структур, создавая предпосылки для более эффективного использования памяти. Начинающим программистам не рекомендуется, тем не менее, работать с нетипизированными указателями.

Оператор присваивания, процедуры выделения хип-памяти и разыменование переменной-указателя составляют основной арсенал средств работы с указателями. Кроме того, для указателей (как для адресов) допустимы обычные отношения сравнения: =, <>,  <, >, <=, >=. Проиллюстрируем эти средства на примере -  программе работы с линейным списком - списком телефонов:

      

      

       program list_tel;{создание списка телефонов}

       uses CRT;

       type refer=^info; {тип - Указатель на запись}

                info= record name,adr,tel:string;

                                      next:refer 

                         end;

       var first,p,pp:refer; {указатели на начало списка и текущие}

              s:string;  

       procedure write_list(start:refer);{вывод всех элементов списка}

       begin repeat with start^ do

                begin writeln(name);

                           writeln(adr);

                           writeln(tel);

                end; start:=start^.next

                  until start=nil;

       end{write_list};

       BEGIN TextBackground(cyan);TextColor(white);ClrScr;

                     window(10,5,40,20);TextBackground(green); ClrScr;

                         new(first);p:=first;pp:=nil;

             repeat if pp<>nil then {образование очередного элемента}

                         begin new(p);pp^.next:=p end;

                         with p^ do { заполнение элемента списка}

                  begin write('Ф.И.О.:'); readln(name);

                        write('Адрес:');  readln(adr);

                        write('Телефон:');readln(tel);

                        next:=nil

                  end;  pp:=p;readln(s)

             until (s=' ');

             writeln('Список телефонов создан');

             write_list(first);writeln('Вывод списка завершен');

      END{list_tel}.

В этой программе элементы списка телефонов создаются циклически до тех пор, пока после заполнения полей очередного элемента списка будет введён символ-пробел. Последний элемент списка имеет нулевой указатель на следующий элемент. После создания списка процедура write_list распечатывает содержимое списка.

Для возврата освободившегося участка хип-памяти используется процедура dispose (p), где p – типизированный указатель, и процедура freemem(p,k), где к – размер в байтах освобождаемого участка для нетипизированного указателя p.

В Турбо Паскале имеется ещё ряд стандартных процедур и функций, работающих с указателями. Приведем  некоторые из них.

Процедура mark(ptr) - запоминает в ptr текущее значение указателя  HeapPtr.

Процедура release(ptr) - освобождение участка хип-памяти от текущего указателя, сохраненного процедурой mark(ptr), до конца хип-памяти.

Функции maxavail и memavail - возвращают размер (в байтах) наибольшего непрерывного участка или общего свободного пространства хип-памяти соответственно.

Функция addr(x) - возвращает указатель, содержащий адрес аргумента x (имя переменной, процедуры, функции). Эту же функцию выполняет операция @x.


 

А также другие работы, которые могут Вас заинтересовать

39639. Совершенствование системы теплоснабжения административного здания №1693 ОАО «Сбербанка России». Перевод работы индивидуального теплового пункта на автономный режим с использованием теплонасосной установки 1.83 MB
  3 Расчет горизонтального кожухотрубчатого конденсатора. Расчёт патрубков.1 Параметры теплоносителя Отопление и вентиляция Горячие водоснабжение Теплоноситель вода Вода Температура 0С 1500700С по ТУ81 ДС 1100700С расчетные параметры 600С Давление в подающем трубопроводе МПа 060 Давление в обратном трубопроводе МПа 045 Тепловые нагрузки приведены в таблицы 2 Таблица 1.3 Расчет горизонтального кожухотрубного конденсатора 2.
39640. ОРГАНИЗАЦИЯ КОРПОРАТИВНОЙ СЕТИ НА ОСНОВЕ ТЕХНОЛОГИИ VDI 12.64 MB
  3 представлен гипервизор VMware ESXi который распределяет все ресурсы физического сервера на нужды виртуальных машин а точнее на нужды их гостевых операционных систем.3 – Сравнение стандартной платформы и платформы с гипервизором В виртуальную машину устанавливается стандартный набор драйверов производства VMware который встроен в ESXi. После этого ВМ будет совместима с любым сервером на котором установлен VMware ESXi. Наиболее популярные решения: Microsoft AppV Citrix XenApp VMware ThinApp.
39641. Технологический процесс изготовления крышки дифференциала грузовой лебедки крана МКРС300 914.5 KB
  С постоянным развитием машиностроения возрастает спрос на продукцию, выпускаемую заводом ОАО «Балткран», в том числе и грузовой лебедки, в которую входит дифференциал, а в месте с этим возрастают требования качества и безопасности изделия.
39642. РАЗРАБОТКА ДИСТАНЦИОННОЙ СИСТЕМЫ УПРАВЛЕНИЯ УЧЕБНЫМ РОБОТОМ 2.7 MB
  Робототехника – прикладная наука, занимающаяся разработкой автоматизированных технических систем и являющаяся важнейшей технической основой интенсификации производства. Робототехника опирается на такие дисциплины, как электроника, механика, информатика
39643. Преобразователь звуковой частоты 251 KB
  Мастер производственного участка обеспечивает работника нужным инвентарем и обеспечивает безопасные условия труда. Из этого следует что все ресурсы потребляются в производстве тремя способами: пропорционально произведенной продукции – сырье энергия заработная плата при сдельной системе оплаты труда и т.; равномерно в течение времени – амортизационные отчисления заработная плата при повременной системе оплаты труда и т.; ситуационно например по мере износа оборудования – материалы и заработная плата ремонтного персонала при...
39644. СИСТЕМЫ АВТОМАТИЧЕСКОГО УПРАВЛЕНИЯ ПОЛЕТОМ 425.42 KB
  ЛАБОРАТОРНАЯ РАБОТА №1 €œИзучение и исследование свойств самолета как объекта управления в продольном движении€. Цель работы Целью работы является изучение и исследование свойств самолета как объекта управления в продольном движении методом математического моделирования а также изучение характера возмущенного движения самолета на управляющие и возмущающие воздействия. Экспериментальное исследование свойств самолета в продольном движении. Исходным материалом для подготовки к лабораторной работе являются значения коэффициентов...
39646. Разработка системы моделирования движения «свободного самолета», с целью внедрения в учебный процесс программы, созданной на основе полученных результатов 6.79 MB
  Методика определения передаточных функций самолета 24 1. Техническое задание на разработку системы моделирования движения свободного самолета 26 2. Построение переходных процессов модели полного продольного движения самолета по приращению управляющих воздействий а так же по приращению импульсных управляющих воздействий. Построение переходных процессов модели короткопериодического движения самолета по приращению управляющих воздействий 36 2.