Home | History | Annotate | Download | only in lib
      1 /* xalloc.h -- malloc with out-of-memory checking
      2 
      3    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
      4    1999, 2000, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
      5 
      6    This program is free software: you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18 
     19 #ifndef XALLOC_H_
     20 # define XALLOC_H_
     21 
     22 # include <stddef.h>
     23 
     24 
     25 # ifdef __cplusplus
     26 extern "C" {
     27 # endif
     28 
     29 
     30 # ifndef __attribute__
     31 #  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
     32 #   define __attribute__(x)
     33 #  endif
     34 # endif
     35 
     36 # ifndef ATTRIBUTE_NORETURN
     37 #  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
     38 # endif
     39 
     40 # ifndef ATTRIBUTE_MALLOC
     41 #  if __GNUC__ >= 3
     42 #   define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
     43 #  else
     44 #   define ATTRIBUTE_MALLOC
     45 #  endif
     46 # endif
     47 
     48 /* This function is always triggered when memory is exhausted.
     49    It must be defined by the application, either explicitly
     50    or by using gnulib's xalloc-die module.  This is the
     51    function to call when one wants the program to die because of a
     52    memory allocation failure.  */
     53 extern void xalloc_die (void) ATTRIBUTE_NORETURN;
     54 
     55 void *xmalloc (size_t s) ATTRIBUTE_MALLOC;
     56 void *xzalloc (size_t s) ATTRIBUTE_MALLOC;
     57 void *xcalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
     58 void *xrealloc (void *p, size_t s);
     59 void *x2realloc (void *p, size_t *pn);
     60 void *xmemdup (void const *p, size_t s) ATTRIBUTE_MALLOC;
     61 char *xstrdup (char const *str) ATTRIBUTE_MALLOC;
     62 
     63 /* Return 1 if an array of N objects, each of size S, cannot exist due
     64    to size arithmetic overflow.  S must be positive and N must be
     65    nonnegative.  This is a macro, not an inline function, so that it
     66    works correctly even when SIZE_MAX < N.
     67 
     68    By gnulib convention, SIZE_MAX represents overflow in size
     69    calculations, so the conservative dividend to use here is
     70    SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
     71    However, malloc (SIZE_MAX) fails on all known hosts where
     72    sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
     73    exactly-SIZE_MAX allocations on such hosts; this avoids a test and
     74    branch when S is known to be 1.  */
     75 # define xalloc_oversized(n, s) \
     76     ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
     77 
     78 
     79 /* In the following macros, T must be an elementary or structure/union or
     80    typedef'ed type, or a pointer to such a type.  To apply one of the
     81    following macros to a function pointer or array type, you need to typedef
     82    it first and use the typedef name.  */
     83 
     84 /* Allocate an object of type T dynamically, with error checking.  */
     85 /* extern t *XMALLOC (typename t); */
     86 # define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
     87 
     88 /* Allocate memory for N elements of type T, with error checking.  */
     89 /* extern t *XNMALLOC (size_t n, typename t); */
     90 # define XNMALLOC(n, t) \
     91     ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
     92 
     93 /* Allocate an object of type T dynamically, with error checking,
     94    and zero it.  */
     95 /* extern t *XZALLOC (typename t); */
     96 # define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
     97 
     98 /* Allocate memory for N elements of type T, with error checking,
     99    and zero it.  */
    100 /* extern t *XCALLOC (size_t n, typename t); */
    101 # define XCALLOC(n, t) \
    102     ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
    103 
    104 
    105 # if HAVE_INLINE
    106 #  define static_inline static inline
    107 # else
    108    void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
    109    void *xnrealloc (void *p, size_t n, size_t s);
    110    void *x2nrealloc (void *p, size_t *pn, size_t s);
    111    char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
    112 # endif
    113 
    114 # ifdef static_inline
    115 
    116 /* Allocate an array of N objects, each with S bytes of memory,
    117    dynamically, with error checking.  S must be nonzero.  */
    118 
    119 static_inline void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
    120 static_inline void *
    121 xnmalloc (size_t n, size_t s)
    122 {
    123   if (xalloc_oversized (n, s))
    124     xalloc_die ();
    125   return xmalloc (n * s);
    126 }
    127 
    128 /* Change the size of an allocated block of memory P to an array of N
    129    objects each of S bytes, with error checking.  S must be nonzero.  */
    130 
    131 static_inline void *
    132 xnrealloc (void *p, size_t n, size_t s)
    133 {
    134   if (xalloc_oversized (n, s))
    135     xalloc_die ();
    136   return xrealloc (p, n * s);
    137 }
    138 
    139 /* If P is null, allocate a block of at least *PN such objects;
    140    otherwise, reallocate P so that it contains more than *PN objects
    141    each of S bytes.  *PN must be nonzero unless P is null, and S must
    142    be nonzero.  Set *PN to the new number of objects, and return the
    143    pointer to the new block.  *PN is never set to zero, and the
    144    returned pointer is never null.
    145 
    146    Repeated reallocations are guaranteed to make progress, either by
    147    allocating an initial block with a nonzero size, or by allocating a
    148    larger block.
    149 
    150    In the following implementation, nonzero sizes are increased by a
    151    factor of approximately 1.5 so that repeated reallocations have
    152    O(N) overall cost rather than O(N**2) cost, but the
    153    specification for this function does not guarantee that rate.
    154 
    155    Here is an example of use:
    156 
    157      int *p = NULL;
    158      size_t used = 0;
    159      size_t allocated = 0;
    160 
    161      void
    162      append_int (int value)
    163        {
    164 	 if (used == allocated)
    165 	   p = x2nrealloc (p, &allocated, sizeof *p);
    166 	 p[used++] = value;
    167        }
    168 
    169    This causes x2nrealloc to allocate a block of some nonzero size the
    170    first time it is called.
    171 
    172    To have finer-grained control over the initial size, set *PN to a
    173    nonzero value before calling this function with P == NULL.  For
    174    example:
    175 
    176      int *p = NULL;
    177      size_t used = 0;
    178      size_t allocated = 0;
    179      size_t allocated1 = 1000;
    180 
    181      void
    182      append_int (int value)
    183        {
    184 	 if (used == allocated)
    185 	   {
    186 	     p = x2nrealloc (p, &allocated1, sizeof *p);
    187 	     allocated = allocated1;
    188 	   }
    189 	 p[used++] = value;
    190        }
    191 
    192    */
    193 
    194 static_inline void *
    195 x2nrealloc (void *p, size_t *pn, size_t s)
    196 {
    197   size_t n = *pn;
    198 
    199   if (! p)
    200     {
    201       if (! n)
    202 	{
    203 	  /* The approximate size to use for initial small allocation
    204 	     requests, when the invoking code specifies an old size of
    205 	     zero.  64 bytes is the largest "small" request for the
    206 	     GNU C library malloc.  */
    207 	  enum { DEFAULT_MXFAST = 64 };
    208 
    209 	  n = DEFAULT_MXFAST / s;
    210 	  n += !n;
    211 	}
    212     }
    213   else
    214     {
    215       /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
    216 	 Check for overflow, so that N * S stays in size_t range.
    217 	 The check is slightly conservative, but an exact check isn't
    218 	 worth the trouble.  */
    219       if ((size_t) -1 / 3 * 2 / s <= n)
    220 	xalloc_die ();
    221       n += (n + 1) / 2;
    222     }
    223 
    224   *pn = n;
    225   return xrealloc (p, n * s);
    226 }
    227 
    228 /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
    229    except it returns char *.  */
    230 
    231 static_inline char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
    232 static_inline char *
    233 xcharalloc (size_t n)
    234 {
    235   return XNMALLOC (n, char);
    236 }
    237 
    238 # endif
    239 
    240 # ifdef __cplusplus
    241 }
    242 
    243 /* C++ does not allow conversions from void * to other pointer types
    244    without a cast.  Use templates to work around the problem when
    245    possible.  */
    246 
    247 template <typename T> inline T *
    248 xrealloc (T *p, size_t s)
    249 {
    250   return (T *) xrealloc ((void *) p, s);
    251 }
    252 
    253 template <typename T> inline T *
    254 xnrealloc (T *p, size_t n, size_t s)
    255 {
    256   return (T *) xnrealloc ((void *) p, n, s);
    257 }
    258 
    259 template <typename T> inline T *
    260 x2realloc (T *p, size_t *pn)
    261 {
    262   return (T *) x2realloc ((void *) p, pn);
    263 }
    264 
    265 template <typename T> inline T *
    266 x2nrealloc (T *p, size_t *pn, size_t s)
    267 {
    268   return (T *) x2nrealloc ((void *) p, pn, s);
    269 }
    270 
    271 template <typename T> inline T *
    272 xmemdup (T const *p, size_t s)
    273 {
    274   return (T *) xmemdup ((void const *) p, s);
    275 }
    276 
    277 # endif
    278 
    279 
    280 #endif /* !XALLOC_H_ */
    281