# PAL - Quickreference: Mem

## Alternate memory management routines

The alternate memory management routines are used in PAL to provide a way to handle out-of memory conditions.

Available functions:

PalMalloc : Malloc replacement with out-of-mem handling
PalRealloc : Realloc replacement with out-of-mem handling
PalCalloc : Calloc replacement with out-of-mem handling
PalFree : Free replacement
PalStrdup : Strdup replacement with out-of-mem handling
SetPalMemFail : Define your own out-of memory handler

## MEM Introduction

When a request for memory is made inside PAL and an out of memory situation results, an error handling routine is called. This routine, by default, does a FatalExit. You can instruct PAL to call a routine of your own when an out-of-mem condition happens though. And you can of course also use these routines in your own programs, in a variety of ways. There are several levels at which you can use these functions in your own program. Level 0: just leave them alone - they will do their work for you inside PAL, but you can continue to use the classic C library routines malloc, calloc, free etc. Level 1: Use just the out-of-memory handler. For example, your application may have important files open which you want to flush prior to exiting, should an out-of-mem condition arise in PAL. You can even try to free some memory that you know can be discarded and tell the calling function to try the allocation again. Level 2: Use them explicitly. That is, you make calls to the replacement routines PalMalloc, PalRealloc, PalFree etc, instead of the ones from the standard lib. You should use the new routines consistently - for example, if you allocate memory using PalMalloc, you should free it with PalFree. Level 3: Use them implicitly. To do this, just #include "palmem.h" in your application. (Put it after the pal.h include). This will activate a set of #defines that change the standard C library memory allocation calls (malloc, calloc, realloc etc.) into the corresponding PAL versions. You will not need to search-and-replace through your existing source code if you want to switch to the PAL routines. You _will_ need to recompile your source though. If you dislike the 'behind-the-screens' way in which macros work, use Level 2 instead of this level. Both Level 2 and Level 3 can be combined with the use of the out-of-memory handler.

## PalMalloc

NAME

            PalMalloc

DESCRIPTION

            Allocates memory like malloc does, but will call the
            out-of-mem handler when it can't allocate the requested
            block.

SYNOPSIS

            #include "pal.h"
            void *PalMalloc(size_t size);

INPUTS

            size - the amount of memory (in bytes) to allocate.

RETURN VALUE

            A pointer to the allocated block of memory. If the
            allocation fails, PalMalloc will call the PalMemFail
            function with the size of the requested block. The
            standard PalMemFail will simply do a FatalExit, but you
            can replace it with a more sophisticated one.

NOTE

            Please see the introductory chapter of this module for
            an explanation of the different possible levels of use
            of the PAL memory allocation routines.

SEE ALSO
  PalRealloc PalCalloc PalFree PalStrdup SetPalMemFail

## PalRealloc

NAME

            PalRealloc

DESCRIPTION

            Reallocates memory like realloc does, but will call the
            out-of-mem handler when it can't allocate the requested
            block.

SYNOPSIS

            #include "pal.h"
            void *PalRealloc(void *p, size_t size);

INPUTS

            p    - a pointer to a memory block returned by PalAlloc,
                   PalRealloc, PalCalloc or PalStrdup.
            size - the amount of memory (in bytes) to allocate.

RETURN VALUE

            A pointer to the new block of memory. If the allocation
            fails, PalMalloc will call the PalMemFail function with
            the size of the requested block. The standard PalMemFail
            will simply do a FatalExit, but you can replace it with a
            more sophisticated one.

NOTE

            See your C compilers documentation for details on how
            realloc works - PalRealloc calls it internally.

            Please see the introductory chapter of this module for
            an explanation of the different possible levels of use
            of the PAL memory allocation routines.

SEE ALSO
  PalMalloc PalCalloc PalFree PalStrdup SetPalMemFail

## PalCalloc

NAME

            PalCalloc

DESCRIPTION

            Allocates memory like calloc does, but will call the
            out-of-mem handler when it can't allocate the requested
            block.

SYNOPSIS

            #include "pal.h"
            void *PalCalloc(size_t n, size_t size);

INPUTS

            n    - the number of elements to allocate
            size - the size of one element

RETURN VALUE

            A pointer to the allocated block of memory. If the
            allocation fails, PalCalloc will call the PalMemFail
            function with the size of the requested block. The
            standard PalMemFail will simply do a FatalExit, but you
            can replace it with a more sophisticated one.

NOTE

            See your C compilers documentation for details on how
            calloc works - PalCalloc calls it internally.

            Please see the introductory chapter of this module for
            an explanation of the different possible levels of use
            of the PAL memory allocation routines.

SEE ALSO
  PalMalloc PalRealloc PalFree PalStrdup SetPalMemFail

## PalFree

NAME

            PalFree

DESCRIPTION

            Frees a block of allocated memory.

SYNOPSIS

            #include "pal.h"
            void PalFree(void *p);

INPUTS

            p    - a pointer to a memory block returned by PalAlloc,
                   PalRealloc, PalCalloc or PalStrdup.

RETURN VALUE

            None.

NOTE

            See your C compilers documentation for details on how
            free works - PalFree calls it internally.

            Please see the introductory chapter of this module for
            an explanation of the different possible levels of use
            of the PAL memory allocation routines. If you use them
            at Level 3, you don't need to care about the double
            pointer - the 'free' replacement macro does this for
            you.

SEE ALSO
  PalMalloc PalRealloc PalFree PalStrdup SetPalMemFail

## PalStrdup

NAME

            PalStrdup

DESCRIPTION

            Duplicates a string like strdup does, but will call the
            out-of-mem handler when it can't allocate the requested
            block. The standard PalMemFail will simply do a FatalExit,
            but you can replace it with a more sophisticated one.

SYNOPSIS

            #include "pal.h"
            char *PalStrdup(char *s);

INPUTS

            s   -  a pointer to a zero-delimited string.

RETURN VALUE

            A copy of the original string.

NOTE

            See your C compilers documentation for details on how
            strdup works - PalStrdup calls it internally.

            Please see the introductory chapter of this module for
            an explanation of the different possible levels of use
            of the PAL memory allocation routines.

SEE ALSO
  PalMalloc PalCalloc PalRealloc PalFree SetPalMemFail

## SetPalMemFail

NAME

            SetPalMemFail

DESCRIPTION

            Use this routine to set your own out of memory handler.
            Pass it the address of your handler function.

            It will return the address of the old handler, in case
            you need to set it back.

            The handler function itself will get the size of the
            block of memory that could not be allocated. It can
            itself try to free up sufficient memory. If it thinks
            it has been successful in doing so, it should return
            TRUE to the caller to trigger another allocation
            attempt. Otherwise, it should either do a FatalExit
            or return FALSE - in this case, the caller of the
            allocation function will get a NULL value return.

            Here's what the default PAL out of memory handler looks
            like:

            int PalMemFail(size_t size)
            {
               FatalExit("PalMemFail: Out of memory !", 99);
               return FALSE; /* not really necessary */
            }

            As you can see, the default handler does not attempt
            to free up memory, it just panicks.

SYNOPSIS

            #include "pal.h"
            void *SetPalMemFail(int (*NewFun)(size_t size));

INPUTS

            NewFun - a pointer to your handler. (As a pointer
            to a function that accepts a size_t and returns
            an int).

RETURN VALUE

            A pointer to the old handler. (As a void *)

NOTE

            While the standard handler listed above does not return,
            your custom version can do so - see the samples below
            for further details.

SAMPLES

            void *MyMemFail(size_t size)
            {
               return FALSE;
            }

            /* ... */
            SetPalMemFail(MyMemFail); /* set new out of mem handler */
            /* ... */

            This handler is the 'passthru' version. It doesn't do anything -
            the behaviour is actually the same as if the whole handler
            mechanism wasn't there at all, and the allocation routines would
            return themselves, directly.

            That's not very useful. This version is more interesting:

            int MyMemFail2(size_t size)
            {
               /* static counter: prevent reentrant calls */
               static int CallCount = 0;
               int Success;

               if(CallCount++) FatalExit("MemFail called recursively !", 1);

               /* attempt to free up sufficient memory */
               Success = FreeSomeMemory(size);

               --CallCount;
               if(!Success) FatalExit("Out of memory !", 2);
               return TRUE;
            }

            /* ... */
            SetPalMemFail(MyMemFail2); /* set new out of mem handler */
            /* ... */

            Notice the precaution that is taken against calling the
            handler recursively. This can easily happen if you call a
            function that itself tries another allocation. MsgBox
            would be a good example - since it opens a window and
            saves the background of it, it will call PalMalloc
            somewhere, and you will end up in your handler again,
            recursively. It is recommended that you use this kind of
            device in your own handler as well.

            Also, be sure to return TRUE IF AND ONLY IF your attempt
            to free up some memory succeeded at least partially. If
            there was no progress at all, either do a FatalExit or
            return FALSE. (If you do the latter, be sure that the
            routine that tried to do the allocation handles this
            case.) If you return TRUE without having freed any
            additional memory, you will end up in an endless loop.

SEE ALSO
  PalMalloc PalCalloc PalRealloc PalFree SetPalMemFail