SysFreeMem Function
SysFreeMem
uses Delphi’s built-in memory
manager to free the memory that P
points to. It
returns zero for success and a non-zero error code if
P
is invalid or
nil
.
SysFreeMem
is a real function.
SysFreeMem
is useful if you are writing your own
memory manager as a filter and want to call Delphi’s memory
manager from your custom memory manager.
If you are not implementing a memory manager, use
Dispose
or FreeMem
, not
SysFreeMem
, to free memory.
FreeMem
and Dispose
already
check for a nil
pointer, so
SysFreeMem
doesn’t have to.
// See SetMemoryManager for an explanation of this memory manager.
// Return True if the memory pointed to by PArray is a valid heap block
// and the guard words are intact. Return false for any error.
function GuardsAreOkay(PArray: PIntegerArray; Fill: Boolean): Boolean;
const
DelphiInUseFlag = 2;
MemMgrFlags = 7;
var
Size: LongWord;
begin
// First get the block size. The size is the long word before
// the start of the block. Delphi sets the size and stores flags
// in the 3 LSBits. Delphi's format is subject to change in future
// releases. The middle bit is set for an allocated block.
PArray := PIntegerArray(PChar(PArray) - SizeOf(Size));
Size := PArray[0];
PArray := PIntegerArray(PChar(PArray) + SizeOf(Size));
if (Size and DelphiInUseFlag) <> DelphiInUseFlag then
begin
Result := False;
Exit;
end;
// Remove Delphi's flag from the size, and subtract the size of
// Delphi's header.
Size := Size and not MemMgrFlags - SizeOf(Size);
// Check the guard words.
if PArray[0] <> AllocatedGuard then
Result := False
// The size includes the 2 guard words, so the last guard word
// is at the size-1 index.
else if PArray[Size div GuardSize - 1] <> AllocatedGuard then
Result := False
else
begin
// If we made it this far, the block looks okay.
Result := True;
// If the caller requests it (DebugFree does), fill the entire
// block with the special FreeFill bit pattern, which helps
// detect problems caused by referring to freed memory.
if Fill then
FillChar(PArray^, Size div 2, FreeFill);
// Change the guard words to FreeGuard even if the caller doesn't
// want the entire block filled.
PArray[0] := FreeGuard;
PArray[Size div GuardSize - 1] := FreeGuard;
end;
end;
// Return zero for success, non-zero for failure.
function DebugFree(Mem: Pointer): Integer;
var
PArray: PIntegerArray;
begin
// Get the pointer to the true start of the memory block.
PArray := PIntegerArray(PChar(Mem) - GuardSize);
if not GuardsAreOkay(PArray, True) then
Result := 1
else
Result := SysFreeMem(PArray);
end;