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