Re: Delphi memory manager.

nobody_at_noplace.not
Date: 07/20/04


Date: Tue, 20 Jul 2004 09:19:37 -0400

On Mon, 19 Jul 2004 23:26:30 GMT, "Martin Harvey (Demon Account)"
<martin@_nospam_pergolesi.demon.co.uk> wrote:

>On Mon, 19 Jul 2004 13:08:53 -0400, nobody@noplace.not wrote:
>
>>I chose to go with the heap based manager because windows handles all the
>>nasties for me. It isn't always a performance decision but I do have to say
>>the small one I posted hasn't disappointed me yet.
>
>BTW - I'm assuming that since it passes calls drectly to windoze, it's
>thread-safe, right?

Yep. The Heap manager does it's own sequencing.

>You don't have any global data in there do you?

Just the memory handle.

Here's the entire source for it...

{------------------------------ Cut Here ------------------------------}

{-------------------------------------------------------------------------}
{ ZTools -- Memory Manager Replacement }
{ June 20, 2004, Version 1 }
{ By L D Blake }
{ }
{ Simple fast and small uses Windows native memory management }
{-------------------------------------------------------------------------}
// windows imports
function HeapCreate(flOptions, dwInitialSize, dwMaximumSize: longword):
THandle; stdcall;
                    external kernel name 'HeapCreate';

function HeapAlloc(hHeap: THandle; dwFlags, dwBytes: longword): Pointer;
stdcall;
                    external kernel name 'HeapAlloc';

function HeapReAlloc(hHeap: THandle; dwFlags: longword; lpMem: Pointer;
dwBytes: longword): Pointer; stdcall;
                    external kernel name 'HeapReAlloc';

function HeapFree(hHeap: THandle; dwFlags: longword; lpMem: Pointer):
LongBool; stdcall;
                    external kernel name 'HeapFree';

function HeapDestroy(hHeap: THandle): longbool; stdcall;
                    external kernel name 'HeapDestroy';

function HeapCompact(hHeap: THandle; dwFlags: longword): longint; stdcall;
                    external kernel name 'HeapCompact';

Const
  HEAP_NO_SERIALIZE = $00001;
  HEAP_GROWABLE = $00002;
  HEAP_GENERATE_EXCEPTIONS = $00004;
  HEAP_ZERO_MEMORY = $00008;
  HEAP_REALLOC_IN_PLACE_ONLY = $00010;
  HEAP_TAIL_CHECKING_ENABLED = $00020;
  HEAP_FREE_CHECKING_ENABLED = $00040;
  HEAP_DISABLE_COALESCE_ON_FREE = $00080;
  HEAP_CREATE_ALIGN_16 = $10000;
  HEAP_CREATE_ENABLE_TRACING = $20000;

Var
  // the heap pointer
  HHeap: THandle; // the heap's handle <--- do not change!

// Allocate memory block.
function SysGetMem(size: Integer): Pointer;
  begin
    Result := HeapAlloc(HHeap,0,size);
  end;

// Deallocate memory block.
function SysFreeMem(p: Pointer): Integer;
  begin
    result := 0; // never fail memory release
    HeapFree(HHeap,0,p);
    HeapCompact(hheap,0);
  end;

// Resize memory block.
function SysReallocMem(p: Pointer; size: Integer): Pointer;
  begin
    if p = nil then
      result := sysgetmem(size)
    else
      result := HeapRealloc(HHeap,0,p,size);
  end;

// kickstart the memory manager
function initallocator : Boolean;
  begin
    HHeap := heapcreate(heap_growable or heap_generate_exceptions,0,0);
    result := (HHeap <> 0);
  end;

// and we're done for the day
function uninitallocator : Boolean;
  begin
    result := heapdestroy(HHeap);
  end;

function GetHeapStatus: THeapStatus;
  begin
    result.TotalAddrSpace := 0;
    result.TotalUncommitted := 0;
    result.TotalCommitted := 0;
    result.TotalAllocated := 0;
    result.TotalFree := 0;
    result.FreeSmall := 0;
    result.FreeBig := 0;
    result.Unused := 0;
    result.Overhead := 0;
    result.HeapErrorCode := 0;
  end;

{------------------------------------- Cut here --------------------------}

To activate this code, just rename the GETMEM.INC file in the borland
RTL/system directory to GEMEM.INC.OLD and drop the above in as GETMEM.INC.
You will have to rebuild the RTL using the provided makefile to activate the
new manager.

Please note, there are several unused constants in the source. These are
provided for completeness.

With the heap manager the GetHeapStatus call returns 0s, and the heap will
generate exceptions when memory gets low or allocation is not possible.

You can improve performance a little by commenting out the HeapCompact call
in SysFreeMem and calling it periodically or manually as part of your
exception handling code.

-----
Laura



Relevant Pages

  • Re: operator new question
    ... > and a memory block is created in heap. ... > OK, if it's on heap, how stack unwinding meachnism can destroy those data ... a pointer has no destructor so ...
    (comp.lang.cpp)
  • Re: thread specific information
    ... Some of these bugs are directly related to the aforementioned "programming techniques", so such things should always be viewed with caution. ... Heap is at best "casually" thread-specific. ... If it keeps that pointer to itself there's no reason for another thread to access it, ... Again, this effectively allocates GLOBALLY visible memory to which only one thread is granted a pointer; but there's nothing to prevent that thread from making a pointer visible to other threads, or to keep other threads from accidentally "scribbling" over the data via a random uninitialized pointer. ...
    (comp.programming.threads)
  • Re: Garbage collectable pinned arrays!
    ... Pinning is an explicit ... I've already given two examples of APIs in widespread use which require a buffer to stay in one position after the initial function call which accepts the pointer. ... That means a one time cost to pin a buffer that lives until the end of the process, if you do this early in the process you won't suffer from fragmentation of the gen0 heap as this object will end on the gen2 heap anyway. ... If this doesn't suits your needs, then you will have to use the Marshal class or GCHandle.Alloc, carefully considering it's costs. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: ptrs validity
    ... I have a pointer that points to an unknown heap memory block, ... hardware checked segment for each allocation. ...
    (comp.lang.c)
  • Heap corruption error.
    ... I'm battling a heap corruption error. ... pBlockHeaderPrev pointer points to the block I just came from. ... The pBlockHeaderNext pointer looks valid in that it's most significant ... reallocated and the write is corrupting the linked list. ...
    (microsoft.public.vc.mfc)