LCOV - code coverage report
Current view: top level - lib - xalloc.h (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 18 21 85.7 %
Date: 2018-01-30 Functions: 4 4 100.0 %

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

Generated by: LCOV version 1.10