Line data Source code
1 : /* xalloc.h -- malloc with out-of-memory checking
2 :
3 : Copyright (C) 1990-2000, 2003-2004, 2006-2016 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 : #ifndef _GL_INLINE_HEADER_BEGIN
26 : #error "Please include config.h first."
27 : #endif
28 : _GL_INLINE_HEADER_BEGIN
29 : #ifndef XALLOC_INLINE
30 : # define XALLOC_INLINE _GL_INLINE
31 : #endif
32 :
33 : #ifdef __cplusplus
34 : extern "C" {
35 : #endif
36 :
37 :
38 : #if __GNUC__ >= 3
39 : # define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
40 : #else
41 : # define _GL_ATTRIBUTE_MALLOC
42 : #endif
43 :
44 : #if ! defined __clang__ && \
45 : (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
46 : # define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
47 : #else
48 : # define _GL_ATTRIBUTE_ALLOC_SIZE(args)
49 : #endif
50 :
51 : /* This function is always triggered when memory is exhausted.
52 : It must be defined by the application, either explicitly
53 : or by using gnulib's xalloc-die module. This is the
54 : function to call when one wants the program to die because of a
55 : memory allocation failure. */
56 : extern _Noreturn void xalloc_die (void);
57 :
58 : void *xmalloc (size_t s)
59 : _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
60 : void *xzalloc (size_t s)
61 : _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
62 : void *xcalloc (size_t n, size_t s)
63 : _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
64 : void *xrealloc (void *p, size_t s)
65 : _GL_ATTRIBUTE_ALLOC_SIZE ((2));
66 : void *x2realloc (void *p, size_t *pn);
67 : void *xmemdup (void const *p, size_t s)
68 : _GL_ATTRIBUTE_ALLOC_SIZE ((2));
69 : char *xstrdup (char const *str)
70 : _GL_ATTRIBUTE_MALLOC;
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 : /* Allocate an array of N objects, each with S bytes of memory,
99 : dynamically, with error checking. S must be nonzero. */
100 :
101 : XALLOC_INLINE void *xnmalloc (size_t n, size_t s)
102 : _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
103 : XALLOC_INLINE void *
104 0 : xnmalloc (size_t n, size_t s)
105 : {
106 0 : if (xalloc_oversized (n, s))
107 0 : xalloc_die ();
108 0 : return xmalloc (n * s);
109 : }
110 :
111 : /* Change the size of an allocated block of memory P to an array of N
112 : objects each of S bytes, with error checking. S must be nonzero. */
113 :
114 : XALLOC_INLINE void *xnrealloc (void *p, size_t n, size_t s)
115 : _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
116 : XALLOC_INLINE void *
117 0 : xnrealloc (void *p, size_t n, size_t s)
118 : {
119 0 : if (xalloc_oversized (n, s))
120 0 : xalloc_die ();
121 0 : return xrealloc (p, n * s);
122 : }
123 :
124 : /* If P is null, allocate a block of at least *PN such objects;
125 : otherwise, reallocate P so that it contains more than *PN objects
126 : each of S bytes. S must be nonzero. Set *PN to the new number of
127 : objects, and return the pointer to the new block. *PN is never set
128 : to zero, and the returned pointer is never null.
129 :
130 : Repeated reallocations are guaranteed to make progress, either by
131 : allocating an initial block with a nonzero size, or by allocating a
132 : larger block.
133 :
134 : In the following implementation, nonzero sizes are increased by a
135 : factor of approximately 1.5 so that repeated reallocations have
136 : O(N) overall cost rather than O(N**2) cost, but the
137 : specification for this function does not guarantee that rate.
138 :
139 : Here is an example of use:
140 :
141 : int *p = NULL;
142 : size_t used = 0;
143 : size_t allocated = 0;
144 :
145 : void
146 : append_int (int value)
147 : {
148 : if (used == allocated)
149 : p = x2nrealloc (p, &allocated, sizeof *p);
150 : p[used++] = value;
151 : }
152 :
153 : This causes x2nrealloc to allocate a block of some nonzero size the
154 : first time it is called.
155 :
156 : To have finer-grained control over the initial size, set *PN to a
157 : nonzero value before calling this function with P == NULL. For
158 : example:
159 :
160 : int *p = NULL;
161 : size_t used = 0;
162 : size_t allocated = 0;
163 : size_t allocated1 = 1000;
164 :
165 : void
166 : append_int (int value)
167 : {
168 : if (used == allocated)
169 : {
170 : p = x2nrealloc (p, &allocated1, sizeof *p);
171 : allocated = allocated1;
172 : }
173 : p[used++] = value;
174 : }
175 :
176 : */
177 :
178 : XALLOC_INLINE void *
179 0 : x2nrealloc (void *p, size_t *pn, size_t s)
180 : {
181 0 : size_t n = *pn;
182 :
183 0 : if (! p)
184 : {
185 0 : if (! n)
186 : {
187 : /* The approximate size to use for initial small allocation
188 : requests, when the invoking code specifies an old size of
189 : zero. This is the largest "small" request for the GNU C
190 : library malloc. */
191 : enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
192 :
193 0 : n = DEFAULT_MXFAST / s;
194 0 : n += !n;
195 : }
196 : }
197 : else
198 : {
199 : /* Set N = floor (1.5 * N) + 1 so that progress is made even if N == 0.
200 : Check for overflow, so that N * S stays in size_t range.
201 : The check may be slightly conservative, but an exact check isn't
202 : worth the trouble. */
203 0 : if ((size_t) -1 / 3 * 2 / s <= n)
204 0 : xalloc_die ();
205 0 : n += n / 2 + 1;
206 : }
207 :
208 0 : *pn = n;
209 0 : return xrealloc (p, n * s);
210 : }
211 :
212 : /* Return a pointer to a new buffer of N bytes. This is like xmalloc,
213 : except it returns char *. */
214 :
215 : XALLOC_INLINE char *xcharalloc (size_t n)
216 : _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
217 : XALLOC_INLINE char *
218 0 : xcharalloc (size_t n)
219 : {
220 0 : return XNMALLOC (n, char);
221 : }
222 :
223 : #ifdef __cplusplus
224 : }
225 :
226 : /* C++ does not allow conversions from void * to other pointer types
227 : without a cast. Use templates to work around the problem when
228 : possible. */
229 :
230 : template <typename T> inline T *
231 : xrealloc (T *p, size_t s)
232 : {
233 : return (T *) xrealloc ((void *) p, s);
234 : }
235 :
236 : template <typename T> inline T *
237 : xnrealloc (T *p, size_t n, size_t s)
238 : {
239 : return (T *) xnrealloc ((void *) p, n, s);
240 : }
241 :
242 : template <typename T> inline T *
243 : x2realloc (T *p, size_t *pn)
244 : {
245 : return (T *) x2realloc ((void *) p, pn);
246 : }
247 :
248 : template <typename T> inline T *
249 : x2nrealloc (T *p, size_t *pn, size_t s)
250 : {
251 : return (T *) x2nrealloc ((void *) p, pn, s);
252 : }
253 :
254 : template <typename T> inline T *
255 : xmemdup (T const *p, size_t s)
256 : {
257 : return (T *) xmemdup ((void const *) p, s);
258 : }
259 :
260 : #endif
261 :
262 : _GL_INLINE_HEADER_END
263 :
264 : #endif /* !XALLOC_H_ */
|