summaryrefslogtreecommitdiff
path: root/lib/xmalloc.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2005-02-23 15:09:34 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2005-02-23 15:09:34 +0000
commit2db5c7115e5b37734993603c0381aab7e62c4be9 (patch)
tree1be931195d1bf1c22bf9a5ca53b9cad9263be6bb /lib/xmalloc.c
parent96aac32803af5414ffeec13a16205d7c456df19d (diff)
downloadmailutils-2db5c7115e5b37734993603c0381aab7e62c4be9.tar.gz
mailutils-2db5c7115e5b37734993603c0381aab7e62c4be9.tar.bz2
Updated by gnulib-sync
Diffstat (limited to 'lib/xmalloc.c')
-rw-r--r--lib/xmalloc.c238
1 files changed, 174 insertions, 64 deletions
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
index a71dc3584..13c249026 100644
--- a/lib/xmalloc.c
+++ b/lib/xmalloc.c
@@ -1,5 +1,7 @@
/* xmalloc.c -- malloc with out of memory checking
- Copyright (C) 1990-1997, 98, 99 Free Software Foundation, Inc.
+
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2002, 2003, 2004 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
@@ -19,64 +21,31 @@
# include <config.h>
#endif
-#include <sys/types.h>
-
-#include <mailutils/error.h>
-
-#if STDC_HEADERS
-# include <stdlib.h>
-#else
-void *calloc ();
-void *malloc ();
-void *realloc ();
-void free ();
-#endif
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(Text) gettext (Text)
-#else
-# define textdomain(Domain)
-# define _(Text) Text
-#endif
-#define N_(Text) Text
-
-#include "error.h"
#include "xalloc.h"
-#ifndef EXIT_FAILURE
-# define EXIT_FAILURE 1
-#endif
-
-#ifndef HAVE_MALLOC
-# error "you must run the autoconf test for a properly working malloc -- see malloc.m4"
-#endif
+#include <stdlib.h>
+#include <string.h>
-#ifndef HAVE_REALLOC
-# error "you must run the autoconf test for a properly working realloc -- see realloc.m4"
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
#endif
-/* Exit value when the requested amount of memory is not available.
- The caller may set it to some other value. */
-int xalloc_exit_failure = EXIT_FAILURE;
-
-/* If non NULL, call this function when memory is exhausted. */
-void (*xalloc_fail_func) PARAMS ((void)) = 0;
+/* Allocate an array of N objects, each with S bytes of memory,
+ dynamically, with error checking. S must be nonzero. */
-/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
- before exiting when memory is exhausted. Goes through gettext. */
-char *const xalloc_msg_memory_exhausted = N_("Memory exhausted");
+static inline void *
+xnmalloc_inline (size_t n, size_t s)
+{
+ void *p;
+ if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
+ xalloc_die ();
+ return p;
+}
-void
-xalloc_die (void)
+void *
+xnmalloc (size_t n, size_t s)
{
- if (xalloc_fail_func)
- (*xalloc_fail_func) ();
- mu_error ("%s", _(xalloc_msg_memory_exhausted));
- /* The `noreturn' cannot be given to error, since it may return if
- its first argument is 0. To help compilers understand the
- xalloc_die does terminate, call exit. */
- exit (xalloc_exit_failure);
+ return xnmalloc_inline (n, s);
}
/* Allocate N bytes of memory dynamically, with error checking. */
@@ -84,36 +53,177 @@ xalloc_die (void)
void *
xmalloc (size_t n)
{
- void *p;
+ return xnmalloc_inline (n, 1);
+}
+
+/* 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. */
- p = malloc (n);
- if (p == 0)
+static inline void *
+xnrealloc_inline (void *p, size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
xalloc_die ();
return p;
}
+void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+ return xnrealloc_inline (p, n, s);
+}
+
/* Change the size of an allocated block of memory P to N bytes,
- with error checking.
- If P is NULL, run xmalloc. */
+ with error checking. */
void *
xrealloc (void *p, size_t n)
{
- p = realloc (p, n);
- if (p == 0)
- xalloc_die ();
- return p;
+ return xnrealloc_inline (p, n, 1);
}
-/* Allocate memory for N elements of S bytes, with error checking. */
+
+/* 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.
+
+ Repeated reallocations are guaranteed to make progress, either by
+ allocating an initial block with a nonzero size, or by allocating a
+ larger block.
+
+ In the following implementation, nonzero sizes are doubled so that
+ repeated reallocations have O(N log N) overall cost rather than
+ O(N**2) cost, but the specification for this function does not
+ guarantee that sizes are doubled.
+
+ Here is an example of use:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ p = x2nrealloc (p, &allocated, sizeof *p);
+ p[used++] = value;
+ }
+
+ This causes x2nrealloc to allocate a block of some nonzero size the
+ first time it is called.
+
+ To have finer-grained control over the initial size, set *PN to a
+ nonzero value before calling this function with P == NULL. For
+ example:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+ size_t allocated1 = 1000;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ {
+ p = x2nrealloc (p, &allocated1, sizeof *p);
+ allocated = allocated1;
+ }
+ p[used++] = value;
+ }
+
+ */
+
+static inline void *
+x2nrealloc_inline (void *p, size_t *pn, size_t s)
+{
+ size_t n = *pn;
+
+ if (! p)
+ {
+ if (! n)
+ {
+ /* The approximate size to use for initial small allocation
+ requests, when the invoking code specifies an old size of
+ zero. 64 bytes is the largest "small" request for the
+ GNU C library malloc. */
+ enum { DEFAULT_MXFAST = 64 };
+
+ n = DEFAULT_MXFAST / s;
+ n += !n;
+ }
+ }
+ else
+ {
+ if (SIZE_MAX / 2 / s < n)
+ xalloc_die ();
+ n *= 2;
+ }
+
+ *pn = n;
+ return xrealloc (p, n * s);
+}
+
+void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+ return x2nrealloc_inline (p, pn, s);
+}
+
+/* If P is null, allocate a block of at least *PN bytes; otherwise,
+ reallocate P so that it contains more than *PN bytes. *PN must be
+ nonzero unless P is null. Set *PN to the new block's size, and
+ return the pointer to the new block. *PN is never set to zero, and
+ the returned pointer is never null. */
+
+void *
+x2realloc (void *p, size_t *pn)
+{
+ return x2nrealloc_inline (p, pn, 1);
+}
+
+/* Allocate S bytes of zeroed memory dynamically, with error checking.
+ There's no need for xnzalloc (N, S), since it would be equivalent
+ to xcalloc (N, S). */
+
+void *
+xzalloc (size_t s)
+{
+ return memset (xmalloc (s), 0, s);
+}
+
+/* Allocate zeroed memory for N elements of S bytes, with error
+ checking. S must be nonzero. */
void *
xcalloc (size_t n, size_t s)
{
void *p;
-
- p = calloc (n, s);
- if (p == 0)
+ /* Test for overflow, since some calloc implementations don't have
+ proper overflow checks. */
+ if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0))
xalloc_die ();
return p;
}
+
+/* Clone an object P of size S, with error checking. There's no need
+ for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
+ need for an arithmetic overflow check. */
+
+void *
+xmemdup (void const *p, size_t s)
+{
+ return memcpy (xmalloc (s), p, s);
+}
+
+/* Clone STRING. */
+
+char *
+xstrdup (char const *string)
+{
+ return xmemdup (string, strlen (string) + 1);
+}

Return to:

Send suggestions and report system problems to the System administrator.