bug-gnulib
[Top][All Lists]
Advanced

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

Re: [bug-gnulib] xmalloc, xnmalloc


From: Paul Eggert
Subject: Re: [bug-gnulib] xmalloc, xnmalloc
Date: Mon, 06 Nov 2006 13:42:16 -0800
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Bruno Haible <address@hidden> writes:

> ! /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
> !    except it returns char *.
> !    xcharalloc (N) is equivalent to XNMALLOC (N, char).  */
>   static inline char *
> ! xcharalloc (size_t n)
>   {
> !   return (char *) xmalloc (n);
>   }

I noticed that the other changes in that patch never invoke
xcharalloc (n); they always invoked XNMALLOC (n, char) instead.
If that's the preferred usage, perhaps we should remove xcharalloc?
On the other hand I prefer not using macros (which is why I added
xcharalloc in the first place).

> ! #define XMALLOC(T) \
> !   ((T *) xmalloc (sizeof (T)))

A minor point: I prefer using lower-case names for macro arguments and
avoiding backslash-newline when defining short macros.

> ! #if HAVE_INLINE
> ! /* xnmalloc performs a division and multiplication by sizeof (T).  Arrange 
> to
> !    perform the division at compile-time and the multiplication with a factor
> !    known at compile-time.  */
> ! # define XNMALLOC(N,T) \
> !    ((T *) (sizeof (T) == 1 \
> !        ? xmalloc (N) \
> !        : xnboundedmalloc(N, (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) 
> ? -1 : -2) / sizeof (T), sizeof (T))))
> ! static inline void *
> ! xnboundedmalloc (size_t n, size_t bound, size_t s)
> ! {
> !   if (n > bound)
> !     xalloc_die ();
> !   return xmalloc (n * s);
> ! }
> ! #else
> ! # define XNMALLOC(N,T) \
> !    ((T *) (sizeof (T) == 1 ? xmalloc (N) : xnmalloc (N, sizeof (T))))
> ! #endif

HAVE_INLINE isn't defined by xalloc.m4 or any of xalloc's
prerequisites.

But in looking into this further, I think it'd be nicer if that
optimization was available to all uses of xnmalloc, not just usages
via XNMALLOC.  Also, I suppose xnrealloc (and XNREALLOC) and
x2nrealloc can use similar optimizations.  So I installed this:

2006-11-06  Paul Eggert  <address@hidden>

        * lib/xalloc.h (xnmalloc, xnrealloc, x2nrealloc): Now static
        inline functions that are identical with the old xnmalloc_inline,
        xnrealloc_inline, x2nrealloc_inline of lib/xmalloc.c.  This is so
        that we can avoid some unnecessary integer multiplications and
        divisions in the common case where the element size is known at
        compile time.
        (XNMALLOC) [HAVE_INLINE]: Remove special case, which is no longer
        needed.
        (xnboundedmalloc): Remove.
        (XMALLOC, XNMALLOC, XZALLOC, XCALLOC): Use lower-case letters for
        arguments, for consistency with rest of this header.
        (xcharalloc): Rewrite using XNMALLOC.
        * lib/xmalloc.c (xnmalloc_inline, xnmalloc, xnrealloc_inline):
        (xnrealloc, x2nrealloc_inline, x2nrealloc): Remove.  The *_inline
        versions have been moved to lib/xalloc.h and renamed to be the
        non-*_inline versions.
        (xmalloc, xrealloc): Implement without reference to the xnmalloc
        and xnrealloc functions, since those functions are now inline and
        now call us.
        (x2realloc): Invoke x2realloc, not x2realloc_inline, to accommodate
        renaming described above.
        * m4/xalloc.m4 (gl_PREREQ_XMALLOC): Remove AC_C_INLINE since
        xmalloc.c no longer uses inline directly.  gl_PREREQ_XALLOC now
        captures the dependency in AC_C_INLINE.

Index: lib/xalloc.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/xalloc.h,v
retrieving revision 1.30
diff -p -u -r1.30 xalloc.h
--- lib/xalloc.h        6 Nov 2006 13:03:10 -0000       1.30
+++ lib/xalloc.h        6 Nov 2006 21:24:17 -0000
@@ -1,7 +1,7 @@
 /* xalloc.h -- malloc with out-of-memory checking
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2003, 2004, 2006 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
@@ -46,13 +46,10 @@ extern "C" {
 extern void xalloc_die (void) ATTRIBUTE_NORETURN;
 
 void *xmalloc (size_t s);
-void *xnmalloc (size_t n, size_t s);
 void *xzalloc (size_t s);
 void *xcalloc (size_t n, size_t s);
 void *xrealloc (void *p, size_t s);
-void *xnrealloc (void *p, size_t n, size_t s);
 void *x2realloc (void *p, size_t *pn);
-void *x2nrealloc (void *p, size_t *pn, size_t s);
 void *xmemdup (void const *p, size_t s);
 char *xstrdup (char const *str);
 
@@ -71,57 +68,142 @@ char *xstrdup (char const *str);
 # define xalloc_oversized(n, s) \
     ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
 
-/* In the following macros, T must be an elementary or structure/union or
-   typedef'ed type, or a pointer to such a type.  To apply one of the
-   following macros to a function pointer or array type, you need to typedef
-   it first and use the typedef name.  */
+/* Allocate an array of N objects, each with S bytes of memory,
+   dynamically, with error checking.  S must be nonzero.  */
 
-/* Allocate an object of type T dynamically, with error checking.  */
-/* extern T *XMALLOC (typename T); */
-#define XMALLOC(T) \
-  ((T *) xmalloc (sizeof (T)))
-
-/* Allocate memory for NMEMB elements of type T, with error checking.  */
-/* extern T *XNMALLOC (size_t nmemb, typename T); */
-#if HAVE_INLINE
-/* xnmalloc performs a division and multiplication by sizeof (T).  Arrange to
-   perform the division at compile-time and the multiplication with a factor
-   known at compile-time.  */
-# define XNMALLOC(N,T) \
-   ((T *) (sizeof (T) == 1 \
-          ? xmalloc (N) \
-          : xnboundedmalloc(N, (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) 
? -1 : -2) / sizeof (T), sizeof (T))))
 static inline void *
-xnboundedmalloc (size_t n, size_t bound, size_t s)
+xnmalloc (size_t n, size_t s)
 {
-  if (n > bound)
+  if (xalloc_oversized (n, s))
     xalloc_die ();
   return xmalloc (n * s);
 }
-#else
-# define XNMALLOC(N,T) \
-   ((T *) (sizeof (T) == 1 ? xmalloc (N) : xnmalloc (N, sizeof (T))))
-#endif
+
+/* 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.  */
+
+static inline void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+  if (xalloc_oversized (n, s))
+    xalloc_die ();
+  return xrealloc (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.
+
+   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 (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_t) -1) / 2 / s < n)
+       xalloc_die ();
+      n *= 2;
+    }
+
+  *pn = n;
+  return xrealloc (p, n * s);
+}
+
+/* In the following macros, T must be an elementary or structure/union or
+   typedef'ed type, or a pointer to such a type.  To apply one of the
+   following macros to a function pointer or array type, you need to typedef
+   it first and use the typedef name.  */
+
+/* Allocate an object of type T dynamically, with error checking.  */
+/* extern t *XMALLOC (typename 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 *) 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)))
+/* extern t *XZALLOC (typename t); */
+#define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
 
-/* Allocate memory for NMEMB elements of type T, with error checking,
+/* Allocate memory for N elements of type T, with error checking,
    and zero it.  */
-/* extern T *XCALLOC (size_t nmemb, typename T); */
-#define XCALLOC(N,T) \
-  ((T *) xcalloc (N, sizeof (T)))
+/* extern t *XCALLOC (size_t n, typename t); */
+#define XCALLOC(n, t) ((t *) xcalloc (n, sizeof (t)))
 
 /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
-   except it returns char *.
-   xcharalloc (N) is equivalent to XNMALLOC (N, char).  */
+   except it returns char *.  */
 static inline char *
 xcharalloc (size_t n)
 {
-  return (char *) xmalloc (n);
+  return XNMALLOC (n, char);
 }
 
 # ifdef __cplusplus
Index: lib/xmalloc.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/xmalloc.c,v
retrieving revision 1.39
diff -p -u -r1.39 xmalloc.c
--- lib/xmalloc.c       13 Sep 2006 22:38:14 -0000      1.39
+++ lib/xmalloc.c       6 Nov 2006 21:24:17 -0000
@@ -38,148 +38,27 @@ enum { HAVE_GNU_CALLOC = 1 };
 enum { HAVE_GNU_CALLOC = 0 };
 #endif
 
-/* Allocate an array of N objects, each with S bytes of memory,
-   dynamically, with error checking.  S must be nonzero.  */
-
-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 *
-xnmalloc (size_t n, size_t s)
-{
-  return xnmalloc_inline (n, s);
-}
-
 /* Allocate N bytes of memory dynamically, with error checking.  */
 
 void *
 xmalloc (size_t n)
 {
-  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.  */
-
-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))
+  void *p = malloc (n);
+  if (!p && 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.  */
 
 void *
 xrealloc (void *p, size_t n)
 {
-  return xnrealloc_inline (p, n, 1);
-}
-
-
-/* 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);
+  p = realloc (p, n);
+  if (!p && n != 0)
+    xalloc_die ();
+  return p;
 }
 
 /* If P is null, allocate a block of at least *PN bytes; otherwise,
@@ -191,7 +70,7 @@ x2nrealloc (void *p, size_t *pn, size_t 
 void *
 x2realloc (void *p, size_t *pn)
 {
-  return x2nrealloc_inline (p, pn, 1);
+  return x2nrealloc (p, pn, 1);
 }
 
 /* Allocate S bytes of zeroed memory dynamically, with error checking.
Index: m4/xalloc.m4
===================================================================
RCS file: /cvsroot/gnulib/gnulib/m4/xalloc.m4,v
retrieving revision 1.16
diff -p -u -r1.16 xalloc.m4
--- m4/xalloc.m4        6 Nov 2006 13:03:10 -0000       1.16
+++ m4/xalloc.m4        6 Nov 2006 21:37:57 -0000
@@ -1,4 +1,4 @@
-# xalloc.m4 serial 14
+# xalloc.m4 serial 15
 dnl Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -20,6 +20,5 @@ AC_DEFUN([gl_PREREQ_XALLOC], [
 
 # Prerequisites of lib/xmalloc.c.
 AC_DEFUN([gl_PREREQ_XMALLOC], [
-  AC_REQUIRE([AC_C_INLINE])
   :
 ])




reply via email to

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