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