Программа на DelphiРефераты >> Программирование и компьютеры >> Программа на Delphi
Отметим, что блок Finally – End выполняется всегда вне зависимости от того, была или не была сгенерирована ИС.
Пример.
i:= 0; n:= 8; Try GetMem (p, 8000); {выделение памяти} i:= n div i; {Деление на нуль. Оператор генерирует ИС} n:= i + 9; Finally FreeMem (p, 8000); {освобождение памяти} End;
14. Указатели
В языке есть средство, разрешающее запрашивать память динамически, т. е. по необходимости. Это позволяет уменьшить объем кода программы и экономно расходовать оперативную память. Такое средство представляет собой специальный тип, называемый указателем. Имеется два типа ука-зателей: указатель на объект некоторого типа и указатель без типа.
Тип Pointer образует указатель без типа. Указатель на тип имеет синтаксис:
^ Имя типа
Примеры объявления указателей:
Type
tDinArr = Array[1 1000, 100] of String[255]; {обычный тип} tDinArrPtr = ^tDinArr; {указатель на тип tDinArr} tRecPtr = ^tRec; {указатель на тип записи, который описан ниже} tTRec = Record {обычный тип-запись} A: Integer; B: Real; C: String[255]; End;
Var DinArr: tDinArr; {обычная запись} DinArrPtr: tDinArrPtr; {указатель на тип} RecPtr: tRecPtr; {указатель на тип-запись} Pn1, Pn2: Pointer; {указатели без типа}
Модули 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 GetMem: function(Size: Integer): Pointer; FreeMem: function(P: Pointer): Integer; ReallocMem: function(P: Pointer; Size: Integer): Pointer; end;
Procedure SetMemoryManager(var MemMgr: TMemoryManager);
Устанавливает менеджер памяти – выполняет операции выделения и освобождения памяти в соответствии с предварительно установленными в менеджере памяти значениями.
14.4. Глобальные переменные AllocMemCount и AllocMemSize
В модуле System объявлены две глобальные переменные, значения которых могут быть использованы при контроле за динамически создаваемыми и разрушаемыми пользовательскими переменными.