Для динамического распределения памяти служат еще две тесно взаимосвязанные процедуры: GetMem и FreeMem. Подобно New и Dispose, они во время вызова выделяют и освобождают память для одной динамической переменной:
- GetMem(var P: Pointer; Size: Integer) — создает в динамической памяти новую динамическую переменную c заданным размером Size и присваивает ее адрес указателю P. Переменная-указатель P может указывать на данные любого типа.
- FreeMem(var P: Pointer [; Size: Integer] ) — освобождает динамическую переменную.
Если в программе используется этот способ распределения памяти, то вызовы GetMem и FreeMem должны соответствовать друг другу. Обращения к GetMem и FreeMem могут полностью соответствовать вызовам New и Dispose.
Пример:
New(P4); // Выделить блок памяти для указателя P4...Dispose(P4); // Освободить блок памяти |
Следующий отрывок программы даст тот же самый результат:
GetMem(P4, SizeOf(ShortString)); // Выделить блок памяти для P4...FreeMem(P4); // Освободить блок памяти |
С помощью процедуры GetMem одной переменной-указателю можно выделить разное количество памяти в зависимости от потребностей. В этом состоит ее основное отличие от процедуры New.
GetMem(P4, 20); // Выделить блок в 20 байт для указателя P4...FreeMem(P4); // Освободить блок памяти |
В данном случае для указателя P4 выделяется меньше памяти, чем может уместиться в переменной типа ShortString, и программист сам должен обеспечить невыход строки за пределы выделенного участка.
В некоторых случаях бывает необходимо перевыделить динамическую память, например, для того чтобы разместить в динамической области больше данных. Для этого предназначена процедура:
ReallocMem(var P: Pointer; Size: Integer) — освобождает блок памяти по значению указателя P и выделяет для указателя новый блок памяти заданного размера Size. Указатель P может иметь значение nil, а параметр Size — значение 0, что влияет на работу процедуры:
- если P = nil и Size = 0, процедура ничего не делает;
- если P = nil и Size <> 0, процедура выделяет новый блок памяти заданного размера, что соответствует вызову процедуры GetMem.
- если P <> nil и Size = 0, процедура освобождает блок памяти, адресуемый указателем P и устанавливает указатель в значение nil. Это соответствует вызову процедуры FreeMem, с той лишь разницей, что FreeMem не очищает указатель;
- если P <> nil и Size <> 0, процедура перевыделяет память для указателя P. Размер нового блока определяется значением Size. Данные из прежнего блока копируются в новый блок. Если новый блок больше прежнего, то приращенный участок остается неинициализированным и содержит случайные данные.