Back to index

nagios-plugins  1.4.16
xalloc.h
Go to the documentation of this file.
00001 /* xalloc.h -- malloc with out-of-memory checking
00002 
00003    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00004    2000, 2003, 2004, 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
00005    Inc.
00006 
00007    This program is free software: you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #ifndef XALLOC_H_
00021 # define XALLOC_H_
00022 
00023 # include <stddef.h>
00024 
00025 
00026 # ifdef __cplusplus
00027 extern "C" {
00028 # endif
00029 
00030 
00031 # ifndef __attribute__
00032 #  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
00033 #   define __attribute__(x)
00034 #  endif
00035 # endif
00036 
00037 # ifndef ATTRIBUTE_NORETURN
00038 #  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
00039 # endif
00040 
00041 # ifndef ATTRIBUTE_MALLOC
00042 #  if __GNUC__ >= 3
00043 #   define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
00044 #  else
00045 #   define ATTRIBUTE_MALLOC
00046 #  endif
00047 # endif
00048 
00049 /* This function is always triggered when memory is exhausted.
00050    It must be defined by the application, either explicitly
00051    or by using gnulib's xalloc-die module.  This is the
00052    function to call when one wants the program to die because of a
00053    memory allocation failure.  */
00054 extern void xalloc_die (void) ATTRIBUTE_NORETURN;
00055 
00056 void *xmalloc (size_t s) ATTRIBUTE_MALLOC;
00057 void *xzalloc (size_t s) ATTRIBUTE_MALLOC;
00058 void *xcalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
00059 void *xrealloc (void *p, size_t s);
00060 void *x2realloc (void *p, size_t *pn);
00061 void *xmemdup (void const *p, size_t s) ATTRIBUTE_MALLOC;
00062 char *xstrdup (char const *str) ATTRIBUTE_MALLOC;
00063 
00064 /* Return 1 if an array of N objects, each of size S, cannot exist due
00065    to size arithmetic overflow.  S must be positive and N must be
00066    nonnegative.  This is a macro, not an inline function, so that it
00067    works correctly even when SIZE_MAX < N.
00068 
00069    By gnulib convention, SIZE_MAX represents overflow in size
00070    calculations, so the conservative dividend to use here is
00071    SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
00072    However, malloc (SIZE_MAX) fails on all known hosts where
00073    sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
00074    exactly-SIZE_MAX allocations on such hosts; this avoids a test and
00075    branch when S is known to be 1.  */
00076 # define xalloc_oversized(n, s) \
00077     ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
00078 
00079 
00080 /* In the following macros, T must be an elementary or structure/union or
00081    typedef'ed type, or a pointer to such a type.  To apply one of the
00082    following macros to a function pointer or array type, you need to typedef
00083    it first and use the typedef name.  */
00084 
00085 /* Allocate an object of type T dynamically, with error checking.  */
00086 /* extern t *XMALLOC (typename t); */
00087 # define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
00088 
00089 /* Allocate memory for N elements of type T, with error checking.  */
00090 /* extern t *XNMALLOC (size_t n, typename t); */
00091 # define XNMALLOC(n, t) \
00092     ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
00093 
00094 /* Allocate an object of type T dynamically, with error checking,
00095    and zero it.  */
00096 /* extern t *XZALLOC (typename t); */
00097 # define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
00098 
00099 /* Allocate memory for N elements of type T, with error checking,
00100    and zero it.  */
00101 /* extern t *XCALLOC (size_t n, typename t); */
00102 # define XCALLOC(n, t) \
00103     ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
00104 
00105 
00106 # if HAVE_INLINE
00107 #  define static_inline static inline
00108 # else
00109 void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
00110 void *xnrealloc (void *p, size_t n, size_t s);
00111 void *x2nrealloc (void *p, size_t *pn, size_t s);
00112 char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
00113 # endif
00114 
00115 # ifdef static_inline
00116 
00117 /* Allocate an array of N objects, each with S bytes of memory,
00118    dynamically, with error checking.  S must be nonzero.  */
00119 
00120 static_inline void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
00121 static_inline void *
00122 xnmalloc (size_t n, size_t s)
00123 {
00124   if (xalloc_oversized (n, s))
00125     xalloc_die ();
00126   return xmalloc (n * s);
00127 }
00128 
00129 /* Change the size of an allocated block of memory P to an array of N
00130    objects each of S bytes, with error checking.  S must be nonzero.  */
00131 
00132 static_inline void *
00133 xnrealloc (void *p, size_t n, size_t s)
00134 {
00135   if (xalloc_oversized (n, s))
00136     xalloc_die ();
00137   return xrealloc (p, n * s);
00138 }
00139 
00140 /* If P is null, allocate a block of at least *PN such objects;
00141    otherwise, reallocate P so that it contains more than *PN objects
00142    each of S bytes.  *PN must be nonzero unless P is null, and S must
00143    be nonzero.  Set *PN to the new number of objects, and return the
00144    pointer to the new block.  *PN is never set to zero, and the
00145    returned pointer is never null.
00146 
00147    Repeated reallocations are guaranteed to make progress, either by
00148    allocating an initial block with a nonzero size, or by allocating a
00149    larger block.
00150 
00151    In the following implementation, nonzero sizes are increased by a
00152    factor of approximately 1.5 so that repeated reallocations have
00153    O(N) overall cost rather than O(N**2) cost, but the
00154    specification for this function does not guarantee that rate.
00155 
00156    Here is an example of use:
00157 
00158      int *p = NULL;
00159      size_t used = 0;
00160      size_t allocated = 0;
00161 
00162      void
00163      append_int (int value)
00164        {
00165          if (used == allocated)
00166            p = x2nrealloc (p, &allocated, sizeof *p);
00167          p[used++] = value;
00168        }
00169 
00170    This causes x2nrealloc to allocate a block of some nonzero size the
00171    first time it is called.
00172 
00173    To have finer-grained control over the initial size, set *PN to a
00174    nonzero value before calling this function with P == NULL.  For
00175    example:
00176 
00177      int *p = NULL;
00178      size_t used = 0;
00179      size_t allocated = 0;
00180      size_t allocated1 = 1000;
00181 
00182      void
00183      append_int (int value)
00184        {
00185          if (used == allocated)
00186            {
00187              p = x2nrealloc (p, &allocated1, sizeof *p);
00188              allocated = allocated1;
00189            }
00190          p[used++] = value;
00191        }
00192 
00193    */
00194 
00195 static_inline void *
00196 x2nrealloc (void *p, size_t *pn, size_t s)
00197 {
00198   size_t n = *pn;
00199 
00200   if (! p)
00201     {
00202       if (! n)
00203         {
00204           /* The approximate size to use for initial small allocation
00205              requests, when the invoking code specifies an old size of
00206              zero.  64 bytes is the largest "small" request for the
00207              GNU C library malloc.  */
00208           enum { DEFAULT_MXFAST = 64 };
00209 
00210           n = DEFAULT_MXFAST / s;
00211           n += !n;
00212         }
00213     }
00214   else
00215     {
00216       /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
00217          Check for overflow, so that N * S stays in size_t range.
00218          The check is slightly conservative, but an exact check isn't
00219          worth the trouble.  */
00220       if ((size_t) -1 / 3 * 2 / s <= n)
00221         xalloc_die ();
00222       n += (n + 1) / 2;
00223     }
00224 
00225   *pn = n;
00226   return xrealloc (p, n * s);
00227 }
00228 
00229 /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
00230    except it returns char *.  */
00231 
00232 static_inline char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
00233 static_inline char *
00234 xcharalloc (size_t n)
00235 {
00236   return XNMALLOC (n, char);
00237 }
00238 
00239 # endif
00240 
00241 # ifdef __cplusplus
00242 }
00243 
00244 /* C++ does not allow conversions from void * to other pointer types
00245    without a cast.  Use templates to work around the problem when
00246    possible.  */
00247 
00248 template <typename T> inline T *
00249 xrealloc (T *p, size_t s)
00250 {
00251   return (T *) xrealloc ((void *) p, s);
00252 }
00253 
00254 template <typename T> inline T *
00255 xnrealloc (T *p, size_t n, size_t s)
00256 {
00257   return (T *) xnrealloc ((void *) p, n, s);
00258 }
00259 
00260 template <typename T> inline T *
00261 x2realloc (T *p, size_t *pn)
00262 {
00263   return (T *) x2realloc ((void *) p, pn);
00264 }
00265 
00266 template <typename T> inline T *
00267 x2nrealloc (T *p, size_t *pn, size_t s)
00268 {
00269   return (T *) x2nrealloc ((void *) p, pn, s);
00270 }
00271 
00272 template <typename T> inline T *
00273 xmemdup (T const *p, size_t s)
00274 {
00275   return (T *) xmemdup ((void const *) p, s);
00276 }
00277 
00278 # endif
00279 
00280 
00281 #endif /* !XALLOC_H_ */