bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 02/13] xwalloc, xwalloc-die, xwallocator: new modules


From: Paul Eggert
Subject: [PATCH 02/13] xwalloc, xwalloc-die, xwallocator: new modules
Date: Sun, 4 Jun 2017 23:45:52 -0700

* lib/xwalloc-die.c, lib/xwalloc.c, lib/xwalloc.h, lib/xwallocator.c:
* modules/xwalloc, modules/xwalloc-die, modules/xwalloc-tests:
* modules/xwallocator, tests/test-xwalloc.c:
New files.
---
 ChangeLog             |   6 ++
 lib/xwalloc-die.c     |  46 +++++++++++++++
 lib/xwalloc.c         |  81 +++++++++++++++++++++++++
 lib/xwalloc.h         | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/xwallocator.c     |   5 ++
 modules/xwalloc       |  29 +++++++++
 modules/xwalloc-die   |  26 ++++++++
 modules/xwalloc-tests |   8 +++
 modules/xwallocator   |  23 ++++++++
 tests/test-xwalloc.c  |  98 +++++++++++++++++++++++++++++++
 10 files changed, 482 insertions(+)
 create mode 100644 lib/xwalloc-die.c
 create mode 100644 lib/xwalloc.c
 create mode 100644 lib/xwalloc.h
 create mode 100644 lib/xwallocator.c
 create mode 100644 modules/xwalloc
 create mode 100644 modules/xwalloc-die
 create mode 100644 modules/xwalloc-tests
 create mode 100644 modules/xwallocator
 create mode 100644 tests/test-xwalloc.c

diff --git a/ChangeLog b/ChangeLog
index 7818861..2f99ccc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2017-06-04  Paul Eggert  <address@hidden>
 
+       xwalloc, xwalloc-die, xwallocator: new modules
+       * lib/xwalloc-die.c, lib/xwalloc.c, lib/xwalloc.h, lib/xwallocator.c:
+       * modules/xwalloc, modules/xwalloc-die, modules/xwalloc-tests:
+       * modules/xwallocator, tests/test-xwalloc.c:
+       New files.
+
        walloc: new module
        * lib/walloc.c, lib/walloc.h, modules/walloc:
        * modules/walloc-tests, tests/test-walloc.c: New files.
diff --git a/lib/xwalloc-die.c b/lib/xwalloc-die.c
new file mode 100644
index 0000000..e2f632a
--- /dev/null
+++ b/lib/xwalloc-die.c
@@ -0,0 +1,46 @@
+/* Report a memory allocation failure and exit
+
+   Copyright (C) 1997-2000, 2002-2004, 2006, 2009-2017 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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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/>.  */
+
+#include <config.h>
+
+#include "xwalloc.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "error.h"
+#include "exitfail.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+void
+xwalloc_die (size_t nbytes)
+{
+  if (nbytes == SIZE_MAX)
+    error (exit_failure, 0, "%s", _("memory exhausted"));
+  else
+    error (exit_failure, 0, _("memory exhausted; %zu bytes requested"),
+           nbytes);
+
+  /* _Noreturn cannot be given to error, since it may return if
+     its first argument is 0.  To help compilers understand that
+     xwalloc_die does not return, call abort.  Also, the abort is a
+     safety feature if exit_failure is 0 (which shouldn't happen).  */
+  abort ();
+}
diff --git a/lib/xwalloc.c b/lib/xwalloc.c
new file mode 100644
index 0000000..bb0c96c
--- /dev/null
+++ b/lib/xwalloc.c
@@ -0,0 +1,81 @@
+/* Checked wary memory allocation with signed integer counts
+
+   Copyright 2017 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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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/>.
+
+   Written by Paul Eggert.  */
+
+#include <config.h>
+
+#include "xwalloc.h"
+
+#include "walloc.h"
+#include <string.h>
+
+void *
+xwgrowalloc (void *a, ptrdiff_t *pn, ptrdiff_t incr, ptrdiff_t nmax,
+             ptrdiff_t itemsize)
+{
+  return wallocmore (a, pn, incr, nmax, itemsize, &xwalloc_allocator);
+}
+
+void *
+xwreallocarray (void *a, ptrdiff_t n, ptrdiff_t s)
+{
+  ptrdiff_t n0 = 0;
+  return xwgrowalloc (a, &n0, n, n, s);
+}
+
+void *
+xwrealloc (void *a, ptrdiff_t n)
+{
+  return xwreallocarray (a, n, 1);
+}
+
+void *
+xwnmalloc (ptrdiff_t n, ptrdiff_t s)
+{
+  return xwreallocarray (NULL, n, s);
+}
+
+void *
+xwmalloc (ptrdiff_t n)
+{
+  return xwnmalloc (n, 1);
+}
+
+void *
+xwcalloc (ptrdiff_t n, ptrdiff_t s)
+{
+  return memset (xwreallocarray (NULL, n, s), 0, n * s);
+}
+
+void *
+xwzalloc (ptrdiff_t n)
+{
+  return xwcalloc (n, 1);
+}
+
+void *
+xwmemdup (void const *a, ptrdiff_t n)
+{
+  return memcpy (xwmalloc (n), a, n);
+}
+
+char *
+xwstrdup (char const *str)
+{
+  return xwmemdup (str, strlen (str) + 1);
+}
diff --git a/lib/xwalloc.h b/lib/xwalloc.h
new file mode 100644
index 0000000..e8332b8
--- /dev/null
+++ b/lib/xwalloc.h
@@ -0,0 +1,160 @@
+/* Checked and wary memory allocation with signed integer counts
+
+   Copyright 2017 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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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/>.
+
+   Written by Paul Eggert.  */
+
+
+/* The memory allocators in this module always succeed, and so have a
+   leading 'x' in their name because they have checked that the result
+   is nonnull.  The allocators are designed for applications that have
+   a single _Noreturn routine xwalloc_die that is called when memory
+   allocation fails.  They are not suitable for libraries designed to
+   work in other applications.
+
+   These allocators operate warily in the sense of walloc.h, so they
+   use ptrdiff_t rather than size_t for byte and object counts.  */
+
+#ifndef XWALLOC_H_
+#define XWALLOC_H_
+
+#include <stddef.h>
+
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef WALLOC_INLINE
+# define WALLOC_INLINE _GL_INLINE
+#endif
+
+#if 3 <= __GNUC__
+# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+#else
+# define _GL_ATTRIBUTE_MALLOC
+#endif
+
+#if 4 < __GNUC__ + (3 <= __GNUC_MINOR__) && !defined __clang__
+# define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
+#else
+# define _GL_ATTRIBUTE_ALLOC_SIZE(args)
+#endif
+
+#if 4 < __GNUC__ + (9 <= __GNUC_MINOR__)
+# define _GL_ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
+#else
+# define _GL_ATTRIBUTE_RETURNS_NONNULL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Report a memory allocation error and exit.  This is suitable for
+   the DIE member of struct allocator.  */
+extern _Noreturn void xwalloc_die (size_t);
+
+/* An allocator using the stdlib functions and xwalloc_die as a DIE
+   function.  */
+extern struct allocator const xwalloc_allocator;
+
+/* Here is an example that allocates at most 1000 items; it dies if
+   this limit is exceeded or if storage is otherwise exhauted.
+
+     float *a;
+     ptrdiff_t used;
+     ptrdiff_t allocated;
+
+     void
+     append_val (float value)
+     {
+       if (used == allocated)
+         a = xwgrowalloc (a, &allocated, 1, 1000, sizeof *a);
+       a[used++] = value;
+     }
+
+   */
+
+/* These are like the similarly-named functions without the leading 'x',
+   except that on allocation failure they call xwalloc_die instead
+   of returning a null pointer.  */
+extern void *xwgrowalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t)
+  _GL_ATTRIBUTE_RETURNS_NONNULL;
+extern void *xwreallocarray (void *, ptrdiff_t, ptrdiff_t)
+  _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3)) _GL_ATTRIBUTE_RETURNS_NONNULL;
+extern void *xwmemdup (void const *, ptrdiff_t) _GL_ATTRIBUTE_ALLOC_SIZE ((2));
+extern char *xwstrdup (char const *) _GL_ATTRIBUTE_MALLOC;
+
+/* These are like the similarly named functions without the leading 'xw',
+   except they take ptrdiff_t instead of size_t arguments, and on
+   allocation failure they call xwalloc_die instead of returning a
+   null pointer.  */
+extern void *xwmalloc (ptrdiff_t)
+  _GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_MALLOC
+  _GL_ATTRIBUTE_RETURNS_NONNULL;
+extern void *xwrealloc (void *, ptrdiff_t)
+  _GL_ATTRIBUTE_ALLOC_SIZE ((2))
+  _GL_ATTRIBUTE_RETURNS_NONNULL;
+extern void *xwcalloc (ptrdiff_t, ptrdiff_t)
+  _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2)) _GL_ATTRIBUTE_MALLOC
+  _GL_ATTRIBUTE_RETURNS_NONNULL;
+
+/* Allocate a block of N*S bytes, calling xwalloc_die on failure.
+   N must be nonnegative and S must be positive.  */
+extern void *xwnmalloc (ptrdiff_t, ptrdiff_t)
+  _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2)) _GL_ATTRIBUTE_MALLOC
+  _GL_ATTRIBUTE_RETURNS_NONNULL;
+
+/* Allocate a zero-initialied block containing N bytes, calling
+   xwalloc_die on failure.  This is like xwcalloc (N, 1).  */
+extern void *xwzalloc (ptrdiff_t)
+  _GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_MALLOC
+  _GL_ATTRIBUTE_RETURNS_NONNULL;
+
+#ifdef __cplusplus
+}
+
+/* C++ does not allow conversions from void * to other pointer types
+   without a cast.  Use templates to work around the problem when
+   possible.  */
+
+template <typename T> inline T *
+xwgrowalloc (T *a, ptrdiff_t *pn, ptrdiff_t incr, ptrdiff_t nmax,
+             ptrdiff_t itemsize)
+{
+  return (T *) xwgrowalloc (a, pn, incr, nmax, itemsize);
+}
+template <typename T> inline T *
+xwmemdup (T *a, ptrdiff_t n)
+{
+  return (T *) xwmemdup ((void *) a, n);
+}
+template <typename T> inline T *
+void *xwrealloc (T *a, ptrdiff_t n)
+{
+  return (T *) xwrealloc (a, n);
+}
+template <typename T> inline T *
+xwreallocarray (T *a, ptrdiff_t n, ptrdiff_t s)
+{
+  return (T *) xwreallocarray ((void *) a, n, s);
+}
+
+#endif
+
+_GL_INLINE_HEADER_END
+
+#endif /* !WALLOC_H_ */
diff --git a/lib/xwallocator.c b/lib/xwallocator.c
new file mode 100644
index 0000000..e5b09a2
--- /dev/null
+++ b/lib/xwallocator.c
@@ -0,0 +1,5 @@
+#include <config.h>
+#include "allocator.h"
+#include "xwalloc.h"
+#include <stdlib.h>
+struct allocator const xwalloc_allocator = {malloc, realloc, free, 
xwalloc_die};
diff --git a/modules/xwalloc b/modules/xwalloc
new file mode 100644
index 0000000..677679f
--- /dev/null
+++ b/modules/xwalloc
@@ -0,0 +1,29 @@
+Description:
+Checked wary memory allocation with signed integer counts
+
+This module depends on xwalloc-die and xwallocator, modules that
+are designed to be overridden by the application as needed.
+
+Files:
+lib/allocator.h
+lib/xwalloc.c
+lib/xwalloc.h
+
+Depends-on:
+walloc
+xwalloc-die
+xwallocator
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += xwalloc.c
+
+Include:
+"xwalloc.h"
+
+License:
+GPL
+
+Maintainer:
+all
diff --git a/modules/xwalloc-die b/modules/xwalloc-die
new file mode 100644
index 0000000..5a90e83
--- /dev/null
+++ b/modules/xwalloc-die
@@ -0,0 +1,26 @@
+Description:
+Report a wary memory allocation failure and exit
+
+Files:
+lib/xwalloc.h
+lib/xwalloc-die.c
+
+Depends-on:
+error
+gettext-h
+exitfail
+stdint
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += xwalloc-die.c
+
+Include:
+"walloc.h"
+
+License:
+GPL
+
+Maintainer:
+all
diff --git a/modules/xwalloc-tests b/modules/xwalloc-tests
new file mode 100644
index 0000000..fbef154
--- /dev/null
+++ b/modules/xwalloc-tests
@@ -0,0 +1,8 @@
+Files:
+tests/test-xwalloc.c
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-xwalloc
+check_PROGRAMS += test-xwalloc
diff --git a/modules/xwallocator b/modules/xwallocator
new file mode 100644
index 0000000..161565b
--- /dev/null
+++ b/modules/xwallocator
@@ -0,0 +1,23 @@
+Description:
+Report a wary memory allocation failure and exit
+
+Files:
+lib/allocator.h
+lib/xwalloc.h
+lib/xwallocator.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += xwallocator.c
+
+Include:
+"xwalloc.h"
+
+License:
+GPL
+
+Maintainer:
+all
diff --git a/tests/test-xwalloc.c b/tests/test-xwalloc.c
new file mode 100644
index 0000000..d368e5d
--- /dev/null
+++ b/tests/test-xwalloc.c
@@ -0,0 +1,98 @@
+/* Test xwalloc module
+   Copyright 2017 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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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/>.  */
+
+#include <config.h>
+
+#include <xwalloc.h>
+
+#include <allocator.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef ptrdiff_t item;
+
+static ptrdiff_t
+test (item *p, ptrdiff_t oldn, ptrdiff_t n)
+{
+  if (!p)
+    return 0;
+  for (ptrdiff_t i = 0; i < oldn; i++)
+    if (p[i] != ~i)
+      abort ();
+  for (ptrdiff_t i = oldn; i < n; i++)
+    p[i] = ~i;
+  return n;
+}
+
+int died;
+
+static void
+test_died (size_t n)
+{
+  died++;
+}
+
+static struct allocator const test_allocator
+  = {malloc, realloc, free, test_died};
+
+int
+main (void)
+{
+  ptrdiff_t oldn = 0;
+  ptrdiff_t n = 1;
+  item *p = xwreallocarray (0, n, sizeof *p);
+  for (int j = 0; j < 10; j++)
+    {
+      oldn = test (p, oldn, n);
+      p = xwgrowalloc (p, &n, 1, n + 2, sizeof *p);
+      oldn = test (p, oldn, n);
+
+      item *q = xwmemdup (p, n * sizeof *p);
+      test (q, n, n);
+      free (q);
+
+      char *s = xwstrdup ("hello");
+      if (!strcmp (s, "Hello"))
+        abort ();
+      free (s);
+
+      q = xwmalloc (n * sizeof *q);
+      test (q, 0, n);
+      q = xwrealloc (q, (n + 1) * sizeof *q);
+      test (q, n, n + 1);
+      free (q);
+
+      q = xwnmalloc (n, sizeof *q);
+      test (q, 0, n);
+      q = xwreallocarray (q, n + 1, sizeof *q);
+      test (q, n, n + 1);
+      free (q);
+
+      q = xwcalloc (n, sizeof *q);
+      for (ptrdiff_t i = 0; i < n; i++)
+        if (q[i])
+          abort ();
+      free (q);
+
+      q = xwzalloc (n * sizeof *q);
+      for (ptrdiff_t i = 0; i < n; i++)
+        if (q[i])
+          abort ();
+      free (q);
+    }
+  free (p);
+  return 0;
+}
-- 
2.9.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]