/* xalloc.h -- malloc with out-of-memory checking
- Copyright (C) 1990-2000, 2003-2004, 2006-2013 Free Software Foundation, Inc.
+ Copyright (C) 1990-2000, 2003-2004, 2006-2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef XALLOC_H_
#define XALLOC_H_
#include <stddef.h>
+#include <stdint.h>
-#include "xalloc-oversized.h"
+#if GNULIB_XALLOC
+# include "idx.h"
+# include "intprops.h"
+#endif
#ifndef _GL_INLINE_HEADER_BEGIN
#error "Please include config.h first."
# define XALLOC_INLINE _GL_INLINE
#endif
+
#ifdef __cplusplus
extern "C" {
#endif
-#if __GNUC__ >= 3
-# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
-#else
-# define _GL_ATTRIBUTE_MALLOC
-#endif
-
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-# define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
-#else
-# define _GL_ATTRIBUTE_ALLOC_SIZE(args)
-#endif
+#if GNULIB_XALLOC_DIE
/* This function is always triggered when memory is exhausted.
It must be defined by the application, either explicitly
or by using gnulib's xalloc-die module. This is the
function to call when one wants the program to die because of a
memory allocation failure. */
-extern _Noreturn void xalloc_die (void);
+/*extern*/ _Noreturn void xalloc_die (void);
+
+#endif /* GNULIB_XALLOC_DIE */
+
+#if GNULIB_XALLOC
void *xmalloc (size_t s)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
void *xrealloc (void *p, size_t s)
_GL_ATTRIBUTE_ALLOC_SIZE ((2));
+void *xreallocarray (void *p, size_t n, size_t s)
+ _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
void *x2realloc (void *p, size_t *pn);
+void *xpalloc (void *pa, idx_t *nitems, idx_t nitems_incr_min,
+ ptrdiff_t nitems_max, idx_t item_size);
void *xmemdup (void const *p, size_t s)
- _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((2));
+ _GL_ATTRIBUTE_ALLOC_SIZE ((2));
char *xstrdup (char const *str)
_GL_ATTRIBUTE_MALLOC;
/* Allocate an object of type T dynamically, with error checking. */
/* extern t *XMALLOC (typename t); */
-#define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
+# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
/* Allocate memory for N elements of type T, with error checking. */
/* extern t *XNMALLOC (size_t n, typename t); */
-#define XNMALLOC(n, t) \
- ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
+# define XNMALLOC(n, t) \
+ ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
/* Allocate an object of type T dynamically, with error checking,
and zero it. */
/* extern t *XZALLOC (typename t); */
-#define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
+# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
/* Allocate memory for N elements of type T, with error checking,
and zero it. */
/* extern t *XCALLOC (size_t n, typename t); */
-#define XCALLOC(n, t) \
- ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
+# define XCALLOC(n, t) \
+ ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
/* Allocate an array of N objects, each with S bytes of memory,
XALLOC_INLINE void *
xnmalloc (size_t n, size_t s)
{
- if (xalloc_oversized (n, s))
- xalloc_die ();
- return xmalloc (n * s);
+ return xreallocarray (NULL, n, s);
}
+/* FIXME: Deprecate this in favor of xreallocarray? */
/* Change the size of an allocated block of memory P to an array of N
objects each of S bytes, with error checking. S must be nonzero. */
XALLOC_INLINE void *
xnrealloc (void *p, size_t n, size_t s)
{
- if (xalloc_oversized (n, s))
- xalloc_die ();
- return xrealloc (p, n * s);
+ return xreallocarray (p, n, s);
}
/* If P is null, allocate a block of at least *PN such objects;
otherwise, reallocate P so that it contains more than *PN objects
- each of S bytes. *PN must be nonzero unless P is null, and S must
- be nonzero. Set *PN to the new number of objects, and return the
- pointer to the new block. *PN is never set to zero, and the
- returned pointer is never null.
+ each of S bytes. S must be nonzero. Set *PN to the new number of
+ objects, and return the pointer to the new block. *PN is never set
+ to zero, and the returned pointer is never null.
Repeated reallocations are guaranteed to make progress, either by
allocating an initial block with a nonzero size, or by allocating a
}
else
{
- /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
- Check for overflow, so that N * S stays in size_t range.
- The check is slightly conservative, but an exact check isn't
- worth the trouble. */
- if ((size_t) -1 / 3 * 2 / s <= n)
+ /* Set N = floor (1.5 * N) + 1 to make progress even if N == 0. */
+ if (INT_ADD_WRAPV (n, (n >> 1) + 1, &n))
xalloc_die ();
- n += (n + 1) / 2;
}
+ p = xreallocarray (p, n, s);
*pn = n;
- return xrealloc (p, n * s);
+ return p;
}
/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
return XNMALLOC (n, char);
}
+#endif /* GNULIB_XALLOC */
+
+
#ifdef __cplusplus
}
+#endif
+
+
+#if GNULIB_XALLOC && defined __cplusplus
/* C++ does not allow conversions from void * to other pointer types
without a cast. Use templates to work around the problem when
}
template <typename T> inline T *
+xreallocarray (T *p, size_t n, size_t s)
+{
+ return (T *) xreallocarray ((void *) p, n, s);
+}
+
+/* FIXME: Deprecate this in favor of xreallocarray? */
+template <typename T> inline T *
xnrealloc (T *p, size_t n, size_t s)
{
- return (T *) xnrealloc ((void *) p, n, s);
+ return xreallocarray (p, n, s);
}
template <typename T> inline T *
return (T *) xmemdup ((void const *) p, s);
}
-#endif
+#endif /* GNULIB_XALLOC && C++ */
+
+_GL_INLINE_HEADER_END
#endif /* !XALLOC_H_ */