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 355624 : {
123 355624 : if (xalloc_oversized (n, s))
124 0 : xalloc_die ();
125 355624 : 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 661744 : {
134 661744 : if (xalloc_oversized (n, s))
135 0 : xalloc_die ();
136 661744 : 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 0 : {
197 0 : size_t n = *pn;
198 :
199 0 : if (! p)
200 : {
201 0 : 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 0 : n = DEFAULT_MXFAST / s;
210 0 : 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 0 : if ((size_t) -1 / 3 * 2 / s <= n)
220 0 : xalloc_die ();
221 0 : n += (n + 1) / 2;
222 : }
223 :
224 0 : *pn = n;
225 0 : 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 0 : {
235 0 : 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_ */
|