Коднянко В.А. |
В языке есть средство, разрешающее запрашивать память динамически, т. е. по необходимости. Это позволяет уменьшить объем кода программы и экономно расходовать оперативную память. Такое средство представляет собой специальный тип, называемый указателем. Имеется два типа ука-зателей: указатель на объект некоторого типа и указатель без типа .Тип Pointer образует указатель без типа. Указатель на тип имеет синтаксис:Имя типа Примеры объявления указателей: Type tDinArr = Array[1 .. 1000, 100] of
String[255]; {обычный тип}
Модули System и SysUtils содержат большое количество типов для работы с указателями. Эти типы могут быть использованы для повышения эффективности пользовательских программ, в которых используются указатели. К их числу относятся: PAnsiString, PString, PByteArray, PCurrency, PExtended и ряд других указателей. Впрочем, эти типы могут быть легко заменены стандартными типами. Например PString эквивалентен ^String и т.д.14.1. Операции с указателями Для указателей допустимы операции присваивания и сравнения. Указателю можно присваивать :содержимое указателя такого же типа ;константу Nil (пустой указатель);адрес объекта с помощью функции Addr;адрес с помощью оператора @;адрес, построенный функцией Ptr.Пример :TrPt:= Nil; Klo1Ptr:= Klo2Ptr; P1:=@Pp; {эквивалентно P1:= Addr(Pp);} P2:= Ptr($B701); 14.2. Стандартные процедуры и функции для работы с указателями Procedure GetMem(Var: P: Pointer; Size: Word); Выделяет блок памяти размера Size и присваивает адрес начала блока указателю P. Procedure FreeMem(Var: P: Pointer; Size: Word); Освобождает блок памяти размера Size, адресованный указателем P. Ниже приведен подробный пример, демонстрирующий экономный процесс копирования текстового файла 't1.txt' в файл 't2.txt' с использованием указателя Buffer.Var F1, F2: file; {объявление файловых переменных} Buffer: PChar; {объявление указателя на строку } begin AssignFile(F1, 't1.txt'); {связывание F1 с файлом 't1.txt'} Reset(F1, 1); {файл открыт для ввода/вывода} AssignFile(F2, 't2.txt'); {связывание F2 с файлом 'text.txt'} Rewrite(F2, 1); {файл открыт для вывода} try Size := FileSize(F1); {вычисления размера файла} GetMem(Buffer, Size); {выделение памяти под чтение файла} try BlockRead(F1, Buffer^, Size); {считывание всего файла 't1.txt'} BlockWrite(F2, Buffer^, Size); {запись в файл 't2.txt'} finally FreeMem(Buffer); {освобождение памяти} end; finally CloseFile(F1); {закрытие файла F1} CloseFile(F2); {закрытие файла F2} end; end; В этом примере объявлен указатель на строку Buffer с завершающим нулем, которая будет использована для копирования файла 't1.txt' в файл 't2.txt'. Для этого оператором GetMem для переменной Buffer^ будет динамически выделен блок памяти размером, равным размеру файла. Далее оператором BlockRead файл 't1.txt', связанный файловой переменной F1, будет считан в Buffer^ и затем оператором BlockWrite переменная Buffer^ будет записана в файл 't2.txt', связанный с файловой переменной F2. Для предотвращения исключительных ситуаций пример содержит два вложенных блока try – finally – end. Внутренний блок обслуживает возможный сбой в ситуации, когда по какой-либо причине файл не удалось прочитать или записать операторами BlockRead или BlockWrite. Такой способ гарантирует освобождение памяти оператором FreeMem как в случае успешного копирования, так и в случае возможного сбоя. Внешний блок обслуживает ситуацию, когда у системы возможно нет того объема памяти, который запрашивает оператор GetMem. В любых вариантах – при успешном или безуспешном копировании файла – следующие за последним finally операторы CloseFile закроют открытые операторами Reset и Rewrite файлы F1 и F2 и позволяет программе продолжить работу. Procedure New(Var: P: Pointer); Создает новую динамическую переменную того типа, на который ссылается указатель. Эквивалентна оператору GetMem(P, SizeOf(P^));Procedure Dispose(Var: P: Pointer); Уничтожает динамическую переменную, на которую указывает P. Эквивалентна оператору FreeMem(P, SizeOf(P^)); Procedure ReallocMem(var P: Pointer; Size: Integer); Процедура работает следующим образом: если P= Nil и Size = 0, то оператор не выполнит никаких действий;если P= Nil и Size > 0, то оператор сработает аналогично GetMem;если P <> Nil и Size = 0, то оператор сработает аналогично FreeMem.Function Addr(X): Pointer; Адрес указанного имени. 14.3. Прочие процедуры и функции для работы с указателями В модулях System и SysUtils объявлены процедуры и функции, которые могут найти применение в пользовательских программах. Ниже дано описание некоторых функций и процедур. Function GetHeapStatus: THeapStatus;Расположена в модуле System. Дает сведение о состоянии распределен-ной и доступной программе памяти. Тип функции имеет вид THeapStatus = record TotalAddrSpace: Cardinal; TotalUncommitted: Cardinal; TotalCommitted: Cardinal; TotalAllocated: Cardinal; TotalFree: Cardinal; FreeSmall: Cardinal; FreeBig: Cardinal; Unused: Cardinal; Overhead: Cardinal; HeapErrorCode: Cardinal; end; Function AllocMem(Size: Cardinal): Pointer; Выделяет блок памяти и устанавливает каждый байт "в нуль". Освобо-ждение памяти можно выполнить с помощью процедуры FreeMem. Procedure GetMemoryManager(var MemMgr: TMemoryManager); Дает текущее состояние менеджера памяти – специальной записи с типом:
TMemoryManager
= record Procedure SetMemoryManager(var MemMgr: TMemoryManager); Устанавливает менеджер памяти – выполняет операции выделения и освобождения памяти в соответствии с предварительно установленными в менеджере памяти значениями. 14.4. Глобальные переменные AllocMemCount и AllocMemSize В модуле System объявлены две глобальные переменные, значения которых могут быть использованы при контроле за динамически создаваемыми и разрушаемыми пользовательскими переменными.AllocMemCount – количество блоков выделенной памяти. AllocMemSize – размер блоков выделенной памяти.
|