LCOV - code coverage report
Current view: top level - shishi/gl - xalloc.h (source / functions) Hit Total Coverage
Test: GNU Shishi Lines: 7 11 63.6 %
Date: 2010-05-20 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 6 33.3 %

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

Generated by: LCOV version 1.8