Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Зачет по инфе.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
336.26 Кб
Скачать

10. Типы с управляемым временем жизни.

Некоторые типы Object Pascal, по сути, являются указателями, хотя программист никогда для переменных этих типов не выделяет и не освобождает память. Более того не используется операция разадресации указателей. Вся работа по выделению и освобождению памяти для переменных этих типов производится автоматически. Операция разадресации также производится автоматически. К этим типам относятся:

•длинные строки (AnsiString),

•динамические массивы

•интерфейсы.

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

10.1 Длинные строки. Механизм подсчета ссылок.

В стандартном Паскале используются только короткие строки String[N]. В памяти такой строке выделяется N+1 байт, первый байт содержит текущую длину строки, а сами символы располагаются начиная со 2-го по счету байта. Поскольку для длины строки в этом случае отводится один байт, максимальная длина короткой строки не может превышать 255 символов. Для объявления короткой строки максимальной длины может использоваться стандартный тип ShortString (эквивалент String[255]).

Директива компилятора {$H} определяет какой тип строки будет подразумеваться под типом String. По умолчанию {$H+} String – длинная строка. При установке {$H-} под типом String будет подразумеваться тип ShortString.

В Windows используются только нуль-терминальные строки, представляющие собой цепочки символов, ограниченные символом #0. Максимальная длина такой строки лимитируется только доступной памятью и может быть очень большой.

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

Механизм работы с памятью для длинных строк следующий. При объявлении длинной строки S: компилятор выделит для переменной 4 байта, достаточные для размещения указателя на область памяти где будут находится данные строки и установит значение указателя в nil. При присваивании строке значения «Hello» программа (а не компилятор!) определит длину цепочки символов «Hello», обратится к ядру операционной системы с требованием выделить для нее участок памяти длиной 5+5=10 байт, поместит в переменную S указатель на выделенную область памяти. Далее программа скопирует в эту область памяти данные строки, т. е. «Hello», завершив ее терминальным нулем, рисунок 5. Кроме этого, как показано на рисунке 5, заполняется два поля, находящиеся по отрицательному

смещению: поле счётчика ссылок и поле длины строки.

Такое размещение на этапе выполнения программы называется динамическим, в то время как размещение на этапе компиляции – статическим. При работе с длинными строками используется механизм подсчета ссылок. С его помощью реализуется «кэширование» памяти: при выполнении оператора

S2:=S;

память для размещения значения переменной S2 не выделяется, в переменную S2 помещается содержимое указателя S, а счетчик ссылок в связанной с ним памяти увеличивается на единицу, рисунок 6.

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

SS:= S+’ World’;

счетчик ссылок уменьшается на единицу, выделяется новая область памяти длиной 11 + 5 = 16 байт, указатель на эту область помещается в S2, а в саму память переписывается цепочка символов «Hello World», терминальный ноль и содержащий единицу счетчик ссылок. Теперь переменные S и S2 будут ссылаться на разные участки памяти, счетчики ссылок которых будут содержать по единице, рисунок 7 Выделенная для размещения строки String область памяти освобождается, если ее счетчик ссылок стал равен нулю. Для строк-констант счетчик ссылок равен -1. Это сделано для предотвращения попыток удаления таких строк.

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

procedure SetLength(var S; NewLength: Integer)

гдеS – строка AnsiString;

NewLength – новая длина строки.

Как уже говорилось в лабораторной работе «Типизированные файлы», существует проблема записи в файл ссылочных типов данных, таких как AnsiString и динамических массивов. Ниже показан пример решения этой проблемы. Программа, приведённая в листинге 6, демонстрирует запись и чтение строк переменной длины (AnsiString) из не типизированного файла. Запись происходит в два этапа:

•запись длины строки (переменная типа Integer);

•запись содержимого строки (объём записываемых данных зависит от реальной длины строки).

Чтение строк происходит в том же порядке. Сначала считывается длина строки, затем выделяется память достаточная для хранения строки указанного размера (SetLength). Производится чтение данных, объем которых равен длине считываемой строки.