#ifndef XALLOC_H_ #define XALLOC_H_ #include #include #include "system.h" /* This function is always triggered when memory is exhausted. It must be defined by the application, either explicitly or by using gnulib's xalloc-die module. This is the function to call when one wants the program to die because of a memory allocation failure. */ extern void xalloc_die(void) __attribute__((noreturn)); void *xmalloc(size_t s); void *xzalloc(size_t s); void *xcalloc(size_t n, size_t s); void *xrealloc(void *p, size_t s); void *x2realloc(void *p, size_t *pn); void *xmemdup(void const *p, size_t s); char *xstrdup(char const *str); /* In the following macros, |t| must be an elementary or structure/union or typedef'ed type, or a pointer to such a type. To apply one of the following macros to a function pointer or array type, you need to typedef it first and use the typedef name. */ /* Allocate an object of type |t| dynamically, with error checking. */ #define XMALLOC(t) ((t *) xmalloc (sizeof (t))) /* Allocate memory for |n| elements of type |t|, with error checking. */ #define XNMALLOC(n, t) \ ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t)))) /* Allocate an object of type |t| dynamically, with error checking, and zero it. */ #define XZALLOC(t) ((t *) xzalloc (sizeof (t))) /* Allocate memory for |n| elements of type |t|, with error checking, and zero it. */ #define XCALLOC(n, t) \ ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t)))) /* Allocate an array of |n| objects, each with |s| bytes of memory, dynamically, with error checking. |s| must be nonzero. */ static inline void *xnmalloc(size_t n, size_t s); static inline void * xnmalloc(size_t n, size_t s) { if (xalloc_oversized (n, s)) xalloc_die(); return xmalloc(n * s); } /* Change the size of an allocated block of memory |p| to an array of |n| objects each of |s| bytes, with error checking. |s| must be nonzero. */ static inline void *xnrealloc(void *p, size_t n, size_t s); static inline void * xnrealloc(void *p, size_t n, size_t s) { if (xalloc_oversized (n, s)) xalloc_die(); return xrealloc(p, n * s); } /* If |p| is |NULL|, allocate a block of at least |*pn| such objects; otherwise, reallocate |p| so that it contains more than |*pn| objects each of |s| bytes. |s| must be nonzero. Set |*pn| to the new number of objects, and return the pointer to the new block. |*PN| is never set to zero, and the returned pointer is never |NULL|. Repeated reallocations are guaranteed to make progress, either by allocating an initial block with a nonzero size, or by allocating a larger block. In the following implementation, nonzero sizes are increased by a factor of approximately 1.5 so that repeated reallocations have $O(N)$ overall cost rather than $O(N^2)$ cost, but the specification for this function does not guarantee that rate. Here is an example of use: |int *p = NULL; size_t used = 0; size_t allocated = 0; void append_int (int value) { if (used == allocated) p = x2nrealloc (p, &allocated, sizeof *p); p[used++] = value; }| This causes |x2nrealloc| to allocate a block of some nonzero size the first time it is called. To have finer-grained control over the initial size, set |*pn| to a nonzero value before calling this function with |p == NULL|. For example: |int *p = NULL; size_t used = 0; size_t allocated = 0; size_t allocated1 = 1000; void append_int (int value) { if (used == allocated) { p = x2nrealloc (p, &allocated1, sizeof *p); allocated = allocated1; } p[used++] = value; }| */ static inline void * x2nrealloc(void *p, size_t *pn, size_t s) { size_t n = *pn; if (!p) { if (!n) { /* The approximate size to use for initial small allocation requests, when the invoking code specifies an old size of zero. This is the largest "small" request for the GNU C library malloc. */ enum { DEFAULT_MXFAST = 64 * sizeof(size_t) / 4 }; n = DEFAULT_MXFAST / s; n += !n; } if (xalloc_oversized (n, s)) xalloc_die(); } else { /* Set $n = \lfloor 1.5 * n \rfloor + 1$ so that progress is made even if $n = 0$. Check for overflow, so that $n * s$ stays in both |ptrdiff_t| and |size_t| range. The check may be slightly conservative, but an exact check isn't worth the trouble. */ if ((PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) / 3 * 2 / s <= n) xalloc_die(); n += n / 2 + 1; } *pn = n; return xrealloc(p, n * s); } /* Return a pointer to a new buffer of |n| bytes. This is like xmalloc, except it returns |char *|. */ static inline char *xcharalloc(size_t n); static inline char * xcharalloc(size_t n) { return XNMALLOC (n, char); } #endif