Mercurial > hg-old > index.cgi
comparison lib/xalloc.h @ 272:d5392bb5da3c 2.5
Added generated files
author | lost |
---|---|
date | Sun, 16 Aug 2009 17:16:49 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
271:3b793ba7a6c6 | 272:d5392bb5da3c |
---|---|
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_ */ |