Разработка программы для компьютера в некотором смысле напо-
минает процесс составления проекта здания, включающий в себя
рассмотрение многочисленных функциональных и эстетических вопро-
сов, влияющих на окончательный результат. Например, некоторые
программы имеют строгое функциональное назначение как дом, кото-
рый имеет определенное число спальных комнат, кухню, две ванные
комнаты и т.д. Другие программы носят менее завершенный характер,
как центры для проведения собраний, которые имеют передвижные
стены и модульные полы, позволяющие лучше приспособить здание для
каждого конкретного случая. В этой главе описывается механизм уп-
равления памятью, позволяющий разрабатывать гибкие программы, ко-
торые могут адаптироваться к конкретным нуждам пользователя и
возможностям ЭВМ.
Следует отметить, что в этой главе используется термин "ло-
гический массив" и термин "физический массив". Логический массив
- это такой массив, который представляется существующим в систе-
ме. Например, матрица на листе бумаги является логическим масси-
вом. Физический массив - это массив, который в действительности
имеется в вычислительной системе. Связь между двумя этими масси-
вами обеспечивается программами по поддержке разреженных масси-
вов. В этой главе рассматривается четыре метода создания разре-
женных массивов: посредством связанного списка, двоичного дерева,
массива указателей и хеширования. Затем будут даны примеры дина-
мического распределения памяти, которое позволяет повысить произ-
водительность программы.
В программе на языке Паскаль информацию в основной памяти
ЭВМ можно хранить двумя способами. Первый способ заключается в
использовании глобальных или локальных переменных, включая масси-
вы и записи, которые предусмотрены в языке Паскаль. Глобальные
переменные занимают постоянное место в памяти во время выполнения
программы. Для локальных переменных память выделяется из стека
ЭВМ. Хотя управление глобальными и локальными переменными на Пас-
кале реализовано эффективно, программист должен знать заранее
объем необходимой памяти для каждого конкретного случая. Другой и
более эффективный способ управления памятью на Паскале обеспечи-
вается применением функций по динамическому управлению памятью.
Таким являются функции "New", "Dispose", "Mark" и "Release".
В обоих методах динамического управлению памятью память вы-
деляется из свободного участка, который не входит в постоянную
область программы, и стека /который используется в Паскале для
хранения локальных переменных/. Эта область называется динамичес-
кой (heap).
Рис.15 иллюстрирует структуру памяти для программы на языке
Турбо Паскаль. Стек увеличивается в нижнем направлении. Объем па-
мяти, необходимой стеку, зависит от характера программы. Напри-
мер, программа со многими рекурсивными функциями будет требовать
много стековой памяти, поскольку при каждом рекурсивном обращении
выделяется участок стековой памяти. Участок выделяемой под прог-
рамму и глобальные переменные памяти имеет постоянную величину и
не изменяется во время выполнения программы. Память для запросов
функции "New" берется из свободного участка памяти, который начи-
нается сразу после глобальных переменных и продолжается до стека.
В исключительных случаях может использоваться для стека область
динамической памяти.
Старшие адреса памяти+------------------+
¦ Хип ¦
¦ ¦
+------------------¦
¦ ¦
¦ ¦
¦ Стек ¦
¦ ¦
+------------------¦
¦Глобальные перемен¦
+------------------¦
¦ ¦
¦ ¦
¦ Программа ¦
¦ ¦
Младшие адреса памяти+------------------+
Рис.15. Использование памяти в программе на языке Турбо Пас-
каль.
Использование динамической памяти зависит от того, какая
функция применяется для освобождения памяти и возвращения ее сис-
теме: функция "Dispose" или пара процедур "Mark" и "Release". Как
указано в справочном руководстве по языку Турбо Паскаль, эти два
способа нельзя никогда смешивать в одной программе. Следователь-
но, вам заранее необходимо решить, каким из способов пользовать-
ся. Для того, чтобы понять, чем эти способы отличаются друг от
друга, ниже дается краткое описание этих функций.