|
|
Лекция
10 |
 |
 |
|
|
Проблема: при решении
задач, в которых предполагается обработка массивов, встает
вопрос об объявлении типов массива, определении переменных и
выделении памяти для хранения элементов массивов. Например,
объявлен тип: |
|
|
type massiv =
array[0..number] of longint; |
|
|
Какие бы
конкретные обработки не включались в данной задаче, пройдет все.
Однако, проблемы начнутся в том случае, если потребуется
обработка не 15000, а 20000 тысяч элементов типа longint. При
попытке запуска данной редакции той же программы возникнет
сообщение |
|
|
«Error 22:
Structure too large.» |
|
|
Это значит:
«Ошибка 22: Структура чересчур объемиста» |
|
|
Теперь в меню Help можно
выбрать пункт Error messages, а затем выбрать пояснение о
сути ошибки. Оно гласит, что максимальный размер для
структурированных типов составляет 65520 байт. Что это значит?
Для хранения одного элемента типа longint требуется 4 байта
памяти, а для массива из 15000 элементов – 60000 байт. При этом
раскладе программа работает правильно. Если же потребуется
хранение 20000 элементов, то это значит и 80000 байт памяти.
Таким образом, превышается максимальный объем памяти. Выход из
данной ситуации, в том числе и для работы с массивами, большими
20000 элементов, в языке Паскаль возможен и представляется в
виде использования динамической памяти и указателей. |
|
|
До сих пор мы имели дело с так
называемыми статическими данными и статическими
переменными. Такие переменные объявляются в начале программы
(в разделе описаний) и существуют до завершения ее работы.
Соответственно, память для содержания этих переменных выделяется
при запуске программы и остается занятой все время, пока
программа работает. |
|
|
Очевидно, что это не самый
рациональный способ использования памяти компьютера. Например,
некоторая переменная может использоваться только однажды в
единственном операторе обширной программы, однако память,
выделенная под эту переменную, остается занята все время, пока
работает программа. А нельзя ли сделать так, чтобы память для
такой переменной выделялась в момент, когда переменная начинает
использоваться, и освобождалась сразу же по завершении ее
использования? И чтобы эту память тут же можно было выделить для
иных данных? Вот такого рода проблемы и могут быть решены с
помощью динамической памяти. |
|
|
Динамическая память,
известная также как «куча», рассматривается в Turbo
Pascal как массив байтов, который имеет объем порядка 300000
байт. Это позволяет обрабатывать массивы гораздо большего
объема. |
|
|
Рассмотрим, как происходит
распределение оперативной памяти в системе программирования
Турбо Паскаль 7.0. Если вы решаете простые задачи, то и
программы у вас, как правило, получаются небольшие. А для
небольших программ, использующих сравнительно немного данных,
проблем с распределением памяти обычно не возникает. Но как
только задачи, стоящие перед вами, усложняются, память сразу же
дает о себе знать: то ее не будет хватать для размещения кодов
самих программ, то недостаточной оказывается область, выделенная
под глобальные или локальные данные. Для того чтобы знать, как
поступать в таких и многих других случаях, необходимо иметь
представление о принципах распределения памяти, используемых в
системе программирования Турбо Паскаль 7.0.
|
|
|
Вся
оперативная память, выделяемая для работы программы, написанной
на Турбо Паскале, делится на сегменты. |
|
|
Сегмент
– это непрерывный участок памяти, размер которой не превышает
65536 байт. |
|
|
ü один
сегмент всегда необходим для размещения кода главной
программы; |
|
|
ü если
программа имеет модульную структуру, то дополнительно по одному
сегменту выделяется для каждого модуля; |
|
|
ü память
обязательно выделяется под системный модуль SYSTEM, - |
|
|
все эти
сегменты носят название сегментов кода. |
|
|
Еще один
сегмент необходим для размещения глобальных переменных и
типизированных констант (к ним относятся статические
переменные и константы, объявленные в главной программе и в
секциях связей модулей). |
|
|
Последним
является сегмент стека, служащий в основном для
размещения локальных данных подпрограмм и внутренних данных
модулей. |
|
|
Еще раз
отметим, что длина любою из этих сегментов не может превосходить
64К. Размеры всех сегментов, кроме сегмента стека определяются в
процессе компиляции и во время работы программы не меняются.
Размер сегмента стека может устанавливаться программистом с
помощью директивы компилятора, имеющей вид |
|
|
{$М <размер
стека>, <мин. объем дин. памяти>, <макс, объем дин. пам.>} |
|
|
Размер
сегмента стека не может превышать 64К; по умолчанию, т. е. в
случае отсутствия соответствующей директивы, размер стека
устанавливается равным 16К. |
|
|
За
сегментом стека размещается оверлейный буфер, размер
которого может устанавливаться программистом. |
|
|
Оставшаяся
свободной область частично или полностью может быть занята
динамической памятью. В ней размещаются динамические
переменные. |
|
|
Сегменты
программы располагаются в памяти в определенном порядке: |
|
|
сначала –
сегмент главной программы, |
|
|
затем –
кодовые сегменты модулей, сегмент кода модуля SYSTEM, |
|
|
и, наконец,
сегмент стека. |
|
|
Все версии
системы программирования Турбо Паскаль кроме последней 7.0 могли
адресовать только 640К байт памяти. То есть, все сегменты,
оверлейный буфер и динамические переменные должны были
помещаться в области памяти с адресами от 0 до 640К. В седьмой
версии это ограничение снято и карта памяти выглядит следующим
образом: |

|
|
Адреса в
персональных компьютерах состоят из двух шестнадцатеричных слов
– адреса сегмента и смещения. Сегмент может
начинаться только с физического адреса кратного 16. Смещение
показывает положение участка памяти относительно начала
сегмента. Задав нужное смещение, можно обратиться к любому байту
данного сегмента. |
|
|
Для работы
с динамической памятью в Турбо Паскале, как и во многих других
языках, используются указатели. Указатель занимает
четыре байта и содержит в двух старших байтах значение адреса
сегмента, а в двух младших – смещение. С помощью указателей
можно размещать в динамической памяти переменные любых типов.
Указатель в этом случае будет ссылаться на первый байт области
памяти, выделенной переменной. |
 |
|