Autoconf, Automake, and Libtool: Memory Management

| #### 9.2.1.2 Memory Management A useful idiom common to many GNU projects is to wrap the memory management functions to localise out of memory handling, naming them with an ``x'` prefix. By doing this, the rest of the project is relieved of having to remember to check for ``NULL'` returns from the various memory functions. These wrappers use the `error` API to report memory exhaustion and abort the program. I have placed the implementation code in ``xmalloc.c'`:
    #if HAVE_CONFIG_H
    #  include <config.h>
    #endif

    #include "common.h"
    #include "error.h"

    void *
    xmalloc (size_t num)
    {
      void *new = malloc (num);
      if (!new)
        sic_fatal ("Memory exhausted");
      return new;
    }

    void *
    xrealloc (void *p, size_t num)
    {
      void *new;

      if (!p)
        return xmalloc (num);

      new = realloc (p, num);
      if (!new)
        sic_fatal ("Memory exhausted");

      return new;
    }

    void *
    xcalloc (size_t num, size_t size)
    {
      void *new = xmalloc (num * size);
      bzero (new, num * size);
      return new;
    }
Notice in the code above, that `xcalloc` is implemented in terms of `xmalloc`, since `calloc` itself is not available in some older C libraries. Also, the `bzero` function is actually deprecated in favour of `memset` in modern C libraries -- I'll explain how to take this into account later in 9.2.3 Beginnings of a ``configure.in'`. Rather than create a separate ``xmalloc.h'` file, which would need to be `#include`d from almost everywhere else, the logical place to declare these functions is in ``common.h'`, since the wrappers will be called from most everywhere else in the code:
    #ifdef __cplusplus
    #  define BEGIN_C_DECLS         extern "C" {
    #  define END_C_DECLS           }
    #else
    #  define BEGIN_C_DECLS
    #  define END_C_DECLS
    #endif

    #define XCALLOC(type, num)                                  \
            ((type *) xcalloc ((num), sizeof(type)))
    #define XMALLOC(type, num)                                  \
            ((type *) xmalloc ((num) * sizeof(type)))
    #define XREALLOC(type, p, num)                              \
            ((type *) xrealloc ((p), (num) * sizeof(type)))
    #define XFREE(stale)                            do {        \
            if (stale) { free (stale);  stale = 0; }            \
                                                    } while (0)

    BEGIN_C_DECLS

    extern void *xcalloc    (size_t num, size_t size);
    extern void *xmalloc    (size_t num);
    extern void *xrealloc   (void *p, size_t num);
    extern char *xstrdup    (const char *string);
    extern char *xstrerror  (int errnum);

    END_C_DECLS
By using the macros defined here, allocating and freeing heap memory is reduced from:
    char **argv = (char **) xmalloc (sizeof (char *) * 3);
    do_stuff (argv);
    if (argv)
      free (argv);
to the simpler and more readable:
    char **argv = XMALLOC (char *, 3);
    do_stuff (argv);
    XFREE (argv);
In the same spirit, I have borrowed ``xstrdup.c'` and ``xstrerror.c'` from project GNU's libiberty. See section 9.1.5 Fallback Function Implementations.

This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html