Возвращает адрес аргумента X. Аналогичный результат возвращает операция @.
ProcedureDispose(var P: Pointer);
Возвращает в кучу фрагмент динамической памяти, который ранее был зарезервирован за типизированным указателем P.
ProcedureFreeMem(var P: Pointer; Size: Integer);
Возвращает в кучу фрагмент динамической памяти, который ранее был зарезервирован за нетипизированным указателем P.
ProcedureGetMem(var P: Pointer; Size: Integer);
Резервирует за нетипизированным указателем P фрагмент динамической памяти требуемого размера Size.
ProcedureNew(varP: Pointer)
Резервирует фрагмент кучи для размещения переменной и помещает в типизированный указатель P адрес первого байта
FunctionSizeOf(X): Integer;
Возвращает длину в байтах внутреннего представления указанного объекта X.
Вся динамическая память Delphi рассматривается как сплошной массив байтов, который называется кучей.
Память под любую динамически размещаемую переменную выделяется процедурой New. Параметром обращения к этой процедуре является типизированный указатель. В результате обращения указатель приобретает значение, соответствующее адресу, начиная с которого можно разместить данные, например:
Var
P1 : ^Integer;
P2 : ^Real;
P : Pointer;
Begin
New(P1);
New(P2);
New(P); //ОШИБКА! P – нетипизированный указатель
.....
End.
После того как указатель приобрел некоторое значение, т.е. стал указывать на конкретный физический байт памяти, по этому адресу можно поместить любое значение соответствующего типа.
Для доступа к величине, адрес которой хранится в указателе, предназначена операция разыменования ^ (^ ставится сразу за указателем). Эту операцию можно использовать как для получения, так и для изменения значения величины. Например,
P1^ := 5; //в область памяти P1 помещено значение 5
P2^ := 2*pi; //в область памяти P2 помещено значение 6.28
Write(P1^, P2^); //пример получения значения из указателя
Схематично, это можно представить следующим образом:
Куча->
...
...
...
6.28
...
P1
P2
Освобождение памяти, выделенной с помощью процедуры New, должно выполняться с помощью процедуры Dispose. Повторное применение данной процедуры к свободному указателю приведет к возникновению ошибки периода исполнения. Чтобы исключить такого рода ошибки, необходимо после применения процедуры Dispose присваивать переменным-указателям значение NIL – пустая ссылка (Например, P1 := nil;).
NIL – это предопределенная константа типа Pointer, соответствующая адресу 0000:0000.
Динамически размещенные данные можно использовать в любом месте программы, где допустимо использование обычных переменных.
Var
P : ^String;
Begin
New(P);
P^ := ‘Это динамическая строка! ’;
WriteLn(P^);
Dispose(P);
P := nil;
End.
Следует учесть, что начальное значение указателя (при его объявлении в разделе переменных) может быть произвольным. Использование указателей, которым не присвоено значение процедурой New или другим способом, не контролируется системой и может привести к непредсказуемым результатам.
Как уже отмечалось, параметром процедуры New может быть только типизированный указатель. Для работы с нетипизированными указателями используются процедуры GetMem и FreeMem:
GetMem(P, Size); //резервирование памяти;
FreeMem(P, Size); //освобождение памяти;
Здесь P – нетипизированный указатель; Size – размер в байтах требуемой или освобождаемой части кучи.
Использование процедур GetMem/FreeMem, как и вообще вся работа с динамической памятью, требует особой осторожности и тщательного соблюдения простого правила: освобождать нужно ровно столько памяти, сколько ее было зарезервировано, и именно с того адреса, с которого она была зарезервирована.