Вся динамическая память в Object Pascal рассматривается как сплошной массив байтов, который называется кучей.
Для того, чтобы какой-то участок динамической памяти можно было использовать для хранений данных, необходимо выделить необходимый объем памяти. Память под любую динамически размещаемую переменную выделяется процедурой New с типизированным указателем в качестве параметра. В результате обращения указатель приобретает значение, соответствующее адресу, начиная с которого можно разместить данные, например:
varpI,pJ: ^Integer;
pR: ^Real;
Begin
New (pI) ;
New (pR) ;
end;
После того как указатель приобрел некоторое значение, т.е. стал указывать на конкретный физический байт памяти, по этому адресу можно разместить любое значение соответствующего типа. Для этого в операторе присваивания сразу за указателем без каких-либо пробелов ставится значок ^, например:
pJ^:=2; {В область памяти pJ помещено значение 2}
pR^:=2*3.14; {В область памяти pR помещено значение 6.28}
Итак, если за указателем нет значка ^, то имеется в виду сам указатель, т.е. адрес, по которому размещены данные. Если за указателем стоит ^, то имеется в виду значение переменной, размещенной по адресу в указателе.
Динамически размещенные данные можно использовать в любом месте программы, где это допустимо для констант и переменных соответствующего типа.
Если в выделенной динамической памяти после работы с ней уже нет необходимости, то ее освобождают с помощью процедуры Dispose с указанием соответствующего указателя. Например,
Dispose(pJ);
Dispose(pR);
Следует заметить, что процедура Dispose не изменяет значения переданного ей указателя, а лишь „возвращает” в кучу память, ранее связанную с этим указателем. Поэтому попытка обращения к памяти по некоторому указателю после процедуры Dispose над этим указателем приведет к ошибке.
Освободившийся указатель, как правило, приравнивают зарезервированному слову nil (как бы «указатель в никуда»).
Для выделения и освобождения памяти под нетипизированные указатели используются соответственно процедуры GetMem и FreeMem:
GetMem(p, size); // резервирование памяти;
FreeMem(p, size); // освобождение памяти.
где р - нетипизированный указатель;
size - размер в байтах выделяемой или освобождаемой части кучи.
Примечание
Освобождать нужно ровно столько памяти, сколько её было выделено, и именно с того адреса, с которого она была выделена.
В таблице 3.12 приведены процедуры и функции для работы с динамической памятью в Object Pascal.
Таблица 3.12.Процедуры и функции для работы с динамической памятью
Function Addr(X):
Pointer;
Возвращает адрес аргумента X. Аналогичный результат возвращает операция @
Procedure Dispose (var P: Pointer);
Возвращает в кучу фрагмент динамической памяти, который ранее был выделен для типизированного указателя P
Procedure FreeMem(var P: Pointer; Size: Integer);
Возвращает в кучу фрагмент динамической памяти, который ранее был выделен для нетипизированного указателя Р
Procedure GetMemvar P: Pointer; Size: Integer) ;
Выделяет для нетипизированного указателя Р фрагмент динамической памяти требуемого размера Size
Procedure New(var P: Pointer) ;
Выделяет фрагмент кучи для размещения переменной и помещает в типизированный указатель Р адрес первого байта
Function SizeOf(X): Integer;
Возвращает длину в байтах внутреннего представления указанного объекта Х
Операционная система Windows имеет собственные средства работы с памятью. За информацией обращайтесь к справочной службе в файлах WIN32.hlp или WIN32S.hlp.