ReallocMem Procedure
ReallocMem
changes the size of a dynamically
allocated block, preserving as much of the previous contents as
possible.
If P
is nil
,
ReallocMem
is just like GetMem
.
If NewSize
is zero, it is just like
FreeMem
, which means P
is not
changed, so it contains an invalid pointer after
ReallocMem
returns.
When possible, ReallocMem
tries to adjust the size
of the current memory block, but if it cannot, it allocates an
entirely new block of the desired size and copies the old data into
the new block. In either case, if NewSize
is
bigger than the current size, the extra memory is not initialized.
ReallocMem
is not a real procedure.
If you have a block that grows incrementally, anticipate future
growth. Instead of frequently increasing the block size in small
steps, increase the size by larger steps less often. Try to call
ReallocMem
as little as possible because
ReallocMem
often fails to reuse the current block.
As the block size grows, the performance penalty for copying the old
block to the new block also grows.
ReallocMem
in Delphi’s default memory
manager is thread-safe, that is, you can call
ReallocMem
from multiple threads simultaneously,
but only if IsMultiThread
is
True.
Delphi’s memory manager assumes that the program will
frequently allocate and free blocks of varying sizes. Most programs
fit this pattern, but a few don’t. If your program often calls
ReallocMem
to incrementally increase the size of a
large block, you might run into performance problems and excessive
wasted memory. The solution is to call ReallocMem
less often, or if you must call it frequently, substitute your own
memory manager that does a better job at increasing a block’s
size without needing to allocate new, larger blocks.
// A trivial list that grows by bounds, not steps.
type
TObjectArray = array[0..MaxInt div SizeOf(TObject) - 1] of TObject;
PObjectArray = ^TObjectArray;
TWholeNumber = 0..MaxInt;
TArray = class
private
fList: PObjectArray;
fCapacity: TWholeNumber;
fCount: TWholeNumber;
procedure Grow;
public
constructor Create;
procedure Add(Obj: TObject);
procedure Remove(Obj: TObject);
property Items[Index: TWholeNumber]: TObject
read GetItem write SetItem;
property Count: TWholeNumber read fCount;
property Capacity: TWholeNumber read fCapacity;
end;
procedure TArray.Add(Obj: TObject);
begin
if Count = Capacity then
Grow;
fList[Count] := Obj;
Inc(fCount);
end;
procedure TArray.Grow;
begin
// When small, grow by 100%, when larger grow by only 50%.
if Capacity < 64 then
fCapacity := Capacity * 2
else
fCapacity := Capacity + Capacity div 2;
ReallocMem(fList, Capacity * SizeOf(TObject));
end;