LCOV - code coverage report
Current view: directory - gltests/gllib - xalloc.h (source / functions) Found Hit Coverage
Test: 000-gnulib-simple Lines: 21 6 28.6 %
Date: 2009-11-12 Functions: 4 2 50.0 %
Colors: not hit hit

       1                 : /* xalloc.h -- malloc with out-of-memory checking
       2                 : 
       3                 :    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
       4                 :    1999, 2000, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
       5                 : 
       6                 :    This program is free software: you can redistribute it and/or modify
       7                 :    it under the terms of the GNU General Public License as published by
       8                 :    the Free Software Foundation; either version 3 of the License, or
       9                 :    (at your option) any later version.
      10                 : 
      11                 :    This program is distributed in the hope that it will be useful,
      12                 :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :    GNU General Public License for more details.
      15                 : 
      16                 :    You should have received a copy of the GNU General Public License
      17                 :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      18                 : 
      19                 : #ifndef XALLOC_H_
      20                 : # define XALLOC_H_
      21                 : 
      22                 : # include <stddef.h>
      23                 : 
      24                 : 
      25                 : # ifdef __cplusplus
      26                 : extern "C" {
      27                 : # endif
      28                 : 
      29                 : 
      30                 : # ifndef __attribute__
      31                 : #  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
      32                 : #   define __attribute__(x)
      33                 : #  endif
      34                 : # endif
      35                 : 
      36                 : # ifndef ATTRIBUTE_NORETURN
      37                 : #  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
      38                 : # endif
      39                 : 
      40                 : # ifndef ATTRIBUTE_MALLOC
      41                 : #  if __GNUC__ >= 3
      42                 : #   define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
      43                 : #  else
      44                 : #   define ATTRIBUTE_MALLOC
      45                 : #  endif
      46                 : # endif
      47                 : 
      48                 : /* This function is always triggered when memory is exhausted.
      49                 :    It must be defined by the application, either explicitly
      50                 :    or by using gnulib's xalloc-die module.  This is the
      51                 :    function to call when one wants the program to die because of a
      52                 :    memory allocation failure.  */
      53                 : extern void xalloc_die (void) ATTRIBUTE_NORETURN;
      54                 : 
      55                 : void *xmalloc (size_t s) ATTRIBUTE_MALLOC;
      56                 : void *xzalloc (size_t s) ATTRIBUTE_MALLOC;
      57                 : void *xcalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
      58                 : void *xrealloc (void *p, size_t s);
      59                 : void *x2realloc (void *p, size_t *pn);
      60                 : void *xmemdup (void const *p, size_t s) ATTRIBUTE_MALLOC;
      61                 : char *xstrdup (char const *str) ATTRIBUTE_MALLOC;
      62                 : 
      63                 : /* Return 1 if an array of N objects, each of size S, cannot exist due
      64                 :    to size arithmetic overflow.  S must be positive and N must be
      65                 :    nonnegative.  This is a macro, not an inline function, so that it
      66                 :    works correctly even when SIZE_MAX < N.
      67                 : 
      68                 :    By gnulib convention, SIZE_MAX represents overflow in size
      69                 :    calculations, so the conservative dividend to use here is
      70                 :    SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
      71                 :    However, malloc (SIZE_MAX) fails on all known hosts where
      72                 :    sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
      73                 :    exactly-SIZE_MAX allocations on such hosts; this avoids a test and
      74                 :    branch when S is known to be 1.  */
      75                 : # define xalloc_oversized(n, s) \
      76                 :     ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
      77                 : 
      78                 : 
      79                 : /* In the following macros, T must be an elementary or structure/union or
      80                 :    typedef'ed type, or a pointer to such a type.  To apply one of the
      81                 :    following macros to a function pointer or array type, you need to typedef
      82                 :    it first and use the typedef name.  */
      83                 : 
      84                 : /* Allocate an object of type T dynamically, with error checking.  */
      85                 : /* extern t *XMALLOC (typename t); */
      86                 : # define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
      87                 : 
      88                 : /* Allocate memory for N elements of type T, with error checking.  */
      89                 : /* extern t *XNMALLOC (size_t n, typename t); */
      90                 : # define XNMALLOC(n, t) \
      91                 :     ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
      92                 : 
      93                 : /* Allocate an object of type T dynamically, with error checking,
      94                 :    and zero it.  */
      95                 : /* extern t *XZALLOC (typename t); */
      96                 : # define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
      97                 : 
      98                 : /* Allocate memory for N elements of type T, with error checking,
      99                 :    and zero it.  */
     100                 : /* extern t *XCALLOC (size_t n, typename t); */
     101                 : # define XCALLOC(n, t) \
     102                 :     ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
     103                 : 
     104                 : 
     105                 : # if HAVE_INLINE
     106                 : #  define static_inline static inline
     107                 : # else
     108                 :    void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
     109                 :    void *xnrealloc (void *p, size_t n, size_t s);
     110                 :    void *x2nrealloc (void *p, size_t *pn, size_t s);
     111                 :    char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
     112                 : # endif
     113                 : 
     114                 : # ifdef static_inline
     115                 : 
     116                 : /* Allocate an array of N objects, each with S bytes of memory,
     117                 :    dynamically, with error checking.  S must be nonzero.  */
     118                 : 
     119                 : static_inline void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
     120                 : static_inline void *
     121                 : xnmalloc (size_t n, size_t s)
     122          355624 : {
     123          355624 :   if (xalloc_oversized (n, s))
     124               0 :     xalloc_die ();
     125          355624 :   return xmalloc (n * s);
     126                 : }
     127                 : 
     128                 : /* Change the size of an allocated block of memory P to an array of N
     129                 :    objects each of S bytes, with error checking.  S must be nonzero.  */
     130                 : 
     131                 : static_inline void *
     132                 : xnrealloc (void *p, size_t n, size_t s)
     133          661744 : {
     134          661744 :   if (xalloc_oversized (n, s))
     135               0 :     xalloc_die ();
     136          661744 :   return xrealloc (p, n * s);
     137                 : }
     138                 : 
     139                 : /* If P is null, allocate a block of at least *PN such objects;
     140                 :    otherwise, reallocate P so that it contains more than *PN objects
     141                 :    each of S bytes.  *PN must be nonzero unless P is null, and S must
     142                 :    be nonzero.  Set *PN to the new number of objects, and return the
     143                 :    pointer to the new block.  *PN is never set to zero, and the
     144                 :    returned pointer is never null.
     145                 : 
     146                 :    Repeated reallocations are guaranteed to make progress, either by
     147                 :    allocating an initial block with a nonzero size, or by allocating a
     148                 :    larger block.
     149                 : 
     150                 :    In the following implementation, nonzero sizes are increased by a
     151                 :    factor of approximately 1.5 so that repeated reallocations have
     152                 :    O(N) overall cost rather than O(N**2) cost, but the
     153                 :    specification for this function does not guarantee that rate.
     154                 : 
     155                 :    Here is an example of use:
     156                 : 
     157                 :      int *p = NULL;
     158                 :      size_t used = 0;
     159                 :      size_t allocated = 0;
     160                 : 
     161                 :      void
     162                 :      append_int (int value)
     163                 :        {
     164                 :          if (used == allocated)
     165                 :            p = x2nrealloc (p, &allocated, sizeof *p);
     166                 :          p[used++] = value;
     167                 :        }
     168                 : 
     169                 :    This causes x2nrealloc to allocate a block of some nonzero size the
     170                 :    first time it is called.
     171                 : 
     172                 :    To have finer-grained control over the initial size, set *PN to a
     173                 :    nonzero value before calling this function with P == NULL.  For
     174                 :    example:
     175                 : 
     176                 :      int *p = NULL;
     177                 :      size_t used = 0;
     178                 :      size_t allocated = 0;
     179                 :      size_t allocated1 = 1000;
     180                 : 
     181                 :      void
     182                 :      append_int (int value)
     183                 :        {
     184                 :          if (used == allocated)
     185                 :            {
     186                 :              p = x2nrealloc (p, &allocated1, sizeof *p);
     187                 :              allocated = allocated1;
     188                 :            }
     189                 :          p[used++] = value;
     190                 :        }
     191                 : 
     192                 :    */
     193                 : 
     194                 : static_inline void *
     195                 : x2nrealloc (void *p, size_t *pn, size_t s)
     196               0 : {
     197               0 :   size_t n = *pn;
     198                 : 
     199               0 :   if (! p)
     200                 :     {
     201               0 :       if (! n)
     202                 :         {
     203                 :           /* The approximate size to use for initial small allocation
     204                 :              requests, when the invoking code specifies an old size of
     205                 :              zero.  64 bytes is the largest "small" request for the
     206                 :              GNU C library malloc.  */
     207                 :           enum { DEFAULT_MXFAST = 64 };
     208                 : 
     209               0 :           n = DEFAULT_MXFAST / s;
     210               0 :           n += !n;
     211                 :         }
     212                 :     }
     213                 :   else
     214                 :     {
     215                 :       /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
     216                 :          Check for overflow, so that N * S stays in size_t range.
     217                 :          The check is slightly conservative, but an exact check isn't
     218                 :          worth the trouble.  */
     219               0 :       if ((size_t) -1 / 3 * 2 / s <= n)
     220               0 :         xalloc_die ();
     221               0 :       n += (n + 1) / 2;
     222                 :     }
     223                 : 
     224               0 :   *pn = n;
     225               0 :   return xrealloc (p, n * s);
     226                 : }
     227                 : 
     228                 : /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
     229                 :    except it returns char *.  */
     230                 : 
     231                 : static_inline char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
     232                 : static_inline char *
     233                 : xcharalloc (size_t n)
     234               0 : {
     235               0 :   return XNMALLOC (n, char);
     236                 : }
     237                 : 
     238                 : # endif
     239                 : 
     240                 : # ifdef __cplusplus
     241                 : }
     242                 : 
     243                 : /* C++ does not allow conversions from void * to other pointer types
     244                 :    without a cast.  Use templates to work around the problem when
     245                 :    possible.  */
     246                 : 
     247                 : template <typename T> inline T *
     248                 : xrealloc (T *p, size_t s)
     249                 : {
     250                 :   return (T *) xrealloc ((void *) p, s);
     251                 : }
     252                 : 
     253                 : template <typename T> inline T *
     254                 : xnrealloc (T *p, size_t n, size_t s)
     255                 : {
     256                 :   return (T *) xnrealloc ((void *) p, n, s);
     257                 : }
     258                 : 
     259                 : template <typename T> inline T *
     260                 : x2realloc (T *p, size_t *pn)
     261                 : {
     262                 :   return (T *) x2realloc ((void *) p, pn);
     263                 : }
     264                 : 
     265                 : template <typename T> inline T *
     266                 : x2nrealloc (T *p, size_t *pn, size_t s)
     267                 : {
     268                 :   return (T *) x2nrealloc ((void *) p, pn, s);
     269                 : }
     270                 : 
     271                 : template <typename T> inline T *
     272                 : xmemdup (T const *p, size_t s)
     273                 : {
     274                 :   return (T *) xmemdup ((void const *) p, s);
     275                 : }
     276                 : 
     277                 : # endif
     278                 : 
     279                 : 
     280                 : #endif /* !XALLOC_H_ */

Generated by: LCOV version 1.7