bug-gnulib
[Top][All Lists]
Advanced

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

Re: [bug-gnulib] xmalloc, xnmalloc


From: Bruno Haible
Subject: Re: [bug-gnulib] xmalloc, xnmalloc
Date: Tue, 7 Nov 2006 14:45:14 +0100
User-agent: KMail/1.9.1

Paul Eggert wrote:
> 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).

That's up to you. I use XNMALLOC (n, char) because once I'm used to
XNMALLOC (n, T) for various other types T, it's easy to understand what
XNMALLOC (n, char) means.

> > ! #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.

As you like. I used an uppercase T because in the C++ community, the first
type template argument is always called 'T'.

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

The purpose of HAVE_INLINE is to avoid bloating the binary when compiling
with a compiler that doesn't support 'inline'. With such a compiler,
AC_C_INLINE defines 'inline' to empty, and such older compilers don't
optimize away unused static functions. So if you compile 30 .c files that
each #include "xalloc.h", you end up with 30 copies of xnmalloc, xnrealloc
etc. in the library or executable. Apart from being bloat, it also hampers
debugging, because when you set a breakpoint in such a function, gdb will
set a breakpoint in one of the copies, chosen randomly, not in all 30 copies.

What I suggest to get around this, is to define these functions with
external linkage when such a compiler is in use. To avoid code duplication,
one needs to move the function definitions to a separate file.
Is this acceptable?

2006-11-06  Bruno Haible  <address@hidden>

        * lib/xalloc.h (xnmalloc, xnrealloc, x2nrealloc, xcharalloc): Move
        definition to xalloc-inline.h. Keep only their declarations, if
        !HAVE_INLINE.
        * lib/xalloc-inline.h: New file, extracted from xalloc.h.
        * lib/xmalloc.c [!HAVE_INLINE]: Include xalloc-inline.h.
        * m4/xalloc.m4 (gl_PREREQ_XALLOC): Require gl_INLINE instead of
        AC_C_INLINE.
        * modules/xalloc (Files): Add lib/xalloc-inline.h, m4/inline.m4.

*** gnulib-20061106/lib/xalloc.h        2006-11-07 01:19:06.000000000 +0100
--- gnulib-20061106-modified/lib/xalloc.h       2006-11-07 02:39:50.000000000 
+0100
***************
*** 70,94 ****
  
  /* Allocate an array of N objects, each with S bytes of memory,
     dynamically, with error checking.  S must be nonzero.  */
! 
! static inline void *
! xnmalloc (size_t n, size_t s)
! {
!   if (xalloc_oversized (n, s))
!     xalloc_die ();
!   return xmalloc (n * s);
! }
  
  /* 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
--- 70,84 ----
  
  /* Allocate an array of N objects, each with S bytes of memory,
     dynamically, with error checking.  S must be nonzero.  */
! #if !HAVE_INLINE
! extern void * xnmalloc (size_t n, size_t s);
! #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.  */
! #if !HAVE_INLINE
! extern void * xnrealloc (void *p, size_t n, size_t s);
! #endif
  
  /* If P is null, allocate a block of at least *PN such objects;
     otherwise, reallocate P so that it contains more than *PN objects
***************
*** 144,179 ****
         }
  
     */
! 
! 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
--- 134,142 ----
         }
  
     */
! #if !HAVE_INLINE
! extern void * x2nrealloc (void *p, size_t *pn, size_t s);
! #endif
  
  /* 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
***************
*** 200,210 ****
  
  /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
     except it returns char *.  */
! static inline char *
! xcharalloc (size_t n)
! {
!   return XNMALLOC (n, char);
! }
  
  # ifdef __cplusplus
  }
--- 163,177 ----
  
  /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
     except it returns char *.  */
! #if !HAVE_INLINE
! extern inline char * xcharalloc (size_t n);
! #endif
! 
! #if HAVE_INLINE
! # define STATIC_INLINE static inline
! # include "xalloc-inline.h"
! # undef STATIC_INLINE
! #endif
  
  # ifdef __cplusplus
  }
*** /dev/null   2003-09-23 19:59:22.000000000 +0200
--- gnulib-20061106-modified/lib/xalloc-inline.h        2006-11-07 
02:40:07.000000000 +0100
***************
*** 0 ****
--- 1,70 ----
+ /* xalloc-inline.h -- inline functions for malloc with out-of-memory checking
+ 
+    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+    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
+    the Free Software Foundation; either version 2, 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, write to the Free Software Foundation,
+    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+ STATIC_INLINE void *
+ xnmalloc (size_t n, size_t s)
+ {
+   if (xalloc_oversized (n, s))
+     xalloc_die ();
+   return xmalloc (n * s);
+ }
+ 
+ STATIC_INLINE void *
+ xnrealloc (void *p, size_t n, size_t s)
+ {
+   if (xalloc_oversized (n, s))
+     xalloc_die ();
+   return xrealloc (p, n * s);
+ }
+ 
+ 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);
+ }
+ 
+ STATIC_INLINE char *
+ xcharalloc (size_t n)
+ {
+   return XNMALLOC (n, char);
+ }
*** gnulib-20061106/lib/xmalloc.c       2006-11-07 01:19:06.000000000 +0100
--- gnulib-20061106-modified/lib/xmalloc.c      2006-11-07 02:39:44.000000000 
+0100
***************
*** 117,119 ****
--- 117,127 ----
  {
    return xmemdup (string, strlen (string) + 1);
  }
+ 
+ /* Implement the functions that could not be declared inline in the header
+    file because the compiler does not support 'inline'.  */
+ #if !HAVE_INLINE
+ # define STATIC_INLINE
+ # include "xalloc-inline.h"
+ # undef STATIC_INLINE
+ #endif
*** gnulib-20061106/m4/xalloc.m4        2006-11-07 01:19:06.000000000 +0100
--- gnulib-20061106-modified/m4/xalloc.m4       2006-11-07 02:41:46.000000000 
+0100
***************
*** 1,4 ****
! # 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,
--- 1,4 ----
! # xalloc.m4 serial 16
  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,
***************
*** 14,20 ****
  
  # Prerequisites of lib/xalloc.h.
  AC_DEFUN([gl_PREREQ_XALLOC], [
!   AC_REQUIRE([AC_C_INLINE])
    :
  ])
  
--- 14,20 ----
  
  # Prerequisites of lib/xalloc.h.
  AC_DEFUN([gl_PREREQ_XALLOC], [
!   AC_REQUIRE([gl_INLINE])
    :
  ])
  
*** gnulib-20061106/modules/xalloc      2006-10-13 01:34:46.000000000 +0200
--- gnulib-20061106-modified/modules/xalloc     2006-11-07 02:41:09.000000000 
+0100
***************
*** 3,10 ****
--- 3,12 ----
  
  Files:
  lib/xalloc.h
+ lib/xalloc-inline.h
  lib/xmalloc.c
  m4/xalloc.m4
+ m4/inline.m4
  
  Depends-on:
  xalloc-die




reply via email to

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