#include #include #include "xalloc.h" #include "error.h" /* 1 if |calloc| is known to be compatible with GNU |calloc|. This matters if we are not also using the |calloc| module, which defines |HAVE_CALLOC_GNU| and supports the GNU API even on non-GNU platforms. */ #if defined HAVE_CALLOC_GNU || (defined __GLIBC__ && !defined __UCLIBC__) enum { HAVE_GNU_CALLOC = 1 }; #else enum { HAVE_GNU_CALLOC = 0 }; #endif void xalloc_die(void) { error(2, 0, "%s", "memory exhausted"); /* |_Noreturn| cannot be given to error, since it may return if its first argument is 0. To help compilers understand the |xalloc_die| does not return, call abort. Also, the abort is a safety feature if |exit_failure| is 0 (which shouldn't happen). */ abort(); } /* Allocate |n| bytes of memory dynamically, with error checking. */ void * xmalloc(size_t n) { void *p = malloc(n); if (!p && n != 0) xalloc_die(); return p; } /* Change the size of an allocated block of memory |p| to |n| bytes, with error checking. */ void * xrealloc(void *p, size_t n) { if (!n && p) { /* The GNU and C99 realloc behaviors disagree here. Act like GNU, even if the underlying realloc is C99. */ free(p); return NULL; } p = realloc(p, n); if (!p && n) xalloc_die(); return p; } /* If |p| is null, allocate a block of at least |*pn| bytes; otherwise, reallocate |p| so that it contains more than |*pn| bytes. |*PN| must be nonzero unless |p| is |NULL|. Set |*pn| to the new block's size, and return the pointer to the new block. |*pn| is never set to zero, and the returned pointer is never |NULL|. */ void * x2realloc(void *p, size_t *pn) { return x2nrealloc(p, pn, 1); } /* Allocate |s| bytes of zeroed memory dynamically, with error checking. There's no need for |xnzalloc (n, s)|, since it would be equivalent to |xcalloc (n, s)|. */ void * xzalloc(size_t s) { return memset (xmalloc(s), 0, s); } /* Allocate zeroed memory for |n| elements of |s| bytes, with error checking. |s| must be nonzero. */ void * xcalloc(size_t n, size_t s) { void *p; /* Test for overflow, since objects with size greater than |PTRDIFF_MAX| cause pointer subtraction to go awry. Omit size-zero tests if |HAVE_GNU_CALLOC|, since GNU calloc never returns |NULL| if successful. */ if (xalloc_oversized (n, s) || (!(p = calloc(n, s)) && (HAVE_GNU_CALLOC || n != 0))) xalloc_die(); return p; } /* Clone an object |p| of size |s|, with error checking. There's no need for |xnmemdup (p, n, s)|, since |xmemdup (p, n * s)| works without any need for an arithmetic overflow check. */ void * xmemdup(void const *p, size_t s) { return memcpy (xmalloc(s), p, s); } /* Clone |string|. */ char * xstrdup(char const *string) { return xmemdup(string, strlen(string) + 1); }