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