|
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 <sic/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.
|