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