/[m4]/m4/gnulib/m4/xmalloc.c
ViewVC logotype

Diff of /m4/gnulib/m4/xmalloc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by gary, Tue Oct 7 14:10:11 2003 UTC revision 1.4 by gary, Thu Nov 13 12:05:58 2003 UTC
# Line 1  Line 1 
1  /* xmalloc.c -- malloc with out of memory checking  /* xmalloc.c -- malloc with out of memory checking
2    
3     Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,     Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
4     1999, 2000, 2002, 2003 Free Software Foundation, Inc.     1999, 2000, 2002, 2003 Free Software Foundation, Inc.
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
# Line 24  Line 24 
24  #include "xalloc.h"  #include "xalloc.h"
25    
26  #include <stdlib.h>  #include <stdlib.h>
27    #include <string.h>
28    
29  #include "gettext.h"  #include "gettext.h"
30  #define _(msgid) gettext (msgid)  #define _(msgid) gettext (msgid)
31  #define N_(msgid) msgid  #define N_(msgid) msgid
32    
33  #include "error.h"  #include "error.h"
 #include "exit.h"  
34  #include "exitfail.h"  #include "exitfail.h"
35    
36  /* The following tests require AC_PREREQ(2.54).  */  #ifndef SIZE_MAX
37    # define SIZE_MAX ((size_t) -1)
38    #endif
39    
40  #ifndef HAVE_MALLOC  #ifndef HAVE_MALLOC
41  "you must run the autoconf test for a GNU libc compatible malloc"  "you must run the autoconf test for a GNU libc compatible malloc"
# Line 58  xalloc_die (void) Line 60  xalloc_die (void)
60    error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));    error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
61    /* The `noreturn' cannot be given to error, since it may return if    /* The `noreturn' cannot be given to error, since it may return if
62       its first argument is 0.  To help compilers understand the       its first argument is 0.  To help compilers understand the
63       xalloc_die does terminate, call exit. */       xalloc_die does terminate, call abort.  */
64    exit (EXIT_FAILURE);    abort ();
65    }
66    
67    /* Allocate an array of N objects, each with S bytes of memory,
68       dynamically, with error checking.  S must be nonzero.  */
69    
70    static inline void *
71    xnmalloc_inline (size_t n, size_t s)
72    {
73      void *p;
74      if (xalloc_oversized (n, s) || ! (p = malloc (n * s)))
75        xalloc_die ();
76      return p;
77    }
78    
79    void *
80    xnmalloc (size_t n, size_t s)
81    {
82      return xnmalloc_inline (n, s);
83  }  }
84    
85  /* Allocate N bytes of memory dynamically, with error checking.  */  /* Allocate N bytes of memory dynamically, with error checking.  */
# Line 67  xalloc_die (void) Line 87  xalloc_die (void)
87  void *  void *
88  xmalloc (size_t n)  xmalloc (size_t n)
89  {  {
90    void *p;    return xnmalloc_inline (n, 1);
91    }
92    
93    /* Change the size of an allocated block of memory P to an array of N
94       objects each of S bytes, with error checking.  S must be nonzero.  */
95    
96    p = malloc (n);  static inline void *
97    if (p == 0)  xnrealloc_inline (void *p, size_t n, size_t s)
98    {
99      if (xalloc_oversized (n, s) || ! (p = realloc (p, n * s)))
100      xalloc_die ();      xalloc_die ();
101    return p;    return p;
102  }  }
103    
104    void *
105    xnrealloc (void *p, size_t n, size_t s)
106    {
107      return xnrealloc_inline (p, n, s);
108    }
109    
110  /* Change the size of an allocated block of memory P to N bytes,  /* Change the size of an allocated block of memory P to N bytes,
111     with error checking.  */     with error checking.  */
112    
113  void *  void *
114  xrealloc (void *p, size_t n)  xrealloc (void *p, size_t n)
115  {  {
116    p = realloc (p, n);    return xnrealloc_inline (p, n, 1);
117    if (p == 0)  }
118      xalloc_die ();  
119    return p;  
120    /* If P is null, allocate a block of at least *PN such objects;
121       otherwise, reallocate P so that it contains more than *PN objects
122       each of S bytes.  *PN must be nonzero unless P is null, and S must
123       be nonzero.  Set *PN to the new number of objects, and return the
124       pointer to the new block.  *PN is never set to zero, and the
125       returned pointer is never null.
126    
127       Repeated reallocations are guaranteed to make progress, either by
128       allocating an initial block with a nonzero size, or by allocating a
129       larger block.
130    
131       In the following implementation, nonzero sizes are doubled so that
132       repeated reallocations have O(N log N) overall cost rather than
133       O(N**2) cost, but the specification for this function does not
134       guarantee that sizes are doubled.
135    
136       Here is an example of use:
137    
138         int *p = NULL;
139         size used = 0;
140         size allocated = 0;
141    
142         void
143         append_int (int value)
144           {
145             if (used == allocated)
146               p = x2nrealloc (p, &allocated, sizeof *p);
147             p[used++] = value;
148           }
149    
150       This causes x2nrealloc to allocate a block of some nonzero size the
151       first time it is called.
152    
153       To have finer-grained control over the initial size, set *PN to a
154       nonzero value before calling this function with P == NULL.  For
155       example:
156    
157         int *p = NULL;
158         size used = 0;
159         size allocated = 0;
160         size allocated1 = 1000;
161    
162         void
163         append_int (int value)
164           {
165             if (used == allocated)
166               {
167                 p = x2nrealloc (p, &allocated1, sizeof *p);
168                 allocated = allocated1;
169               }
170             p[used++] = value;
171           }
172    
173       */
174    
175    static inline void *
176    x2nrealloc_inline (void *p, size_t *pn, size_t s)
177    {
178      size_t n = *pn;
179    
180      if (! p)
181        {
182          if (! n)
183            {
184              /* The approximate size to use for initial small allocation
185                 requests, when the invoking code specifies an old size of
186                 zero.  64 bytes is the largest "small" request for the
187                 GNU C library malloc.  */
188              enum { DEFAULT_MXFAST = 64 };
189    
190              n = DEFAULT_MXFAST / s;
191              n += !n;
192            }
193        }
194      else
195        {
196          if (SIZE_MAX / 2 / s < n)
197            xalloc_die ();
198          n *= 2;
199        }
200    
201      *pn = n;
202      return xrealloc (p, n * s);
203  }  }
204    
205  /* Allocate memory for N elements of S bytes, with error checking.  */  void *
206    x2nrealloc (void *p, size_t *pn, size_t s)
207    {
208      return x2nrealloc_inline (p, pn, s);
209    }
210    
211    /* If P is null, allocate a block of at least *PN bytes; otherwise,
212       reallocate P so that it contains more than *PN bytes.  *PN must be
213       nonzero unless P is null.  Set *PN to the new block's size, and
214       return the pointer to the new block.  *PN is never set to zero, and
215       the returned pointer is never null.  */
216    
217    void *
218    x2realloc (void *p, size_t *pn)
219    {
220      return x2nrealloc_inline (p, pn, 1);
221    }
222    
223    /* Allocate S bytes of zeroed memory dynamically, with error checking.
224       There's no need for xnzalloc (N, S), since it would be equivalent
225       to xcalloc (N, S).  */
226    
227    void *
228    xzalloc (size_t s)
229    {
230      return memset (xmalloc (s), 0, s);
231    }
232    
233    /* Allocate zeroed memory for N elements of S bytes, with error
234       checking.  S must be nonzero.  */
235    
236  void *  void *
237  xcalloc (size_t n, size_t s)  xcalloc (size_t n, size_t s)
238  {  {
239    void *p;    void *p;
240      /* Test for overflow, since some calloc implementations don't have
241    p = calloc (n, s);       proper overflow checks.  */
242    if (p == 0)    if (xalloc_oversized (n, s) || ! (p = calloc (n, s)))
243      xalloc_die ();      xalloc_die ();
244    return p;    return p;
245  }  }
246    
247    /* Clone an object P of size S, with error checking.  There's no need
248       for xnclone (P, N, S), since xclone (P, N * S) works without any
249       need for an arithmetic overflow check.  */
250    
251    void *
252    xclone (void const *p, size_t s)
253    {
254      return memcpy (xmalloc (s), p, s);
255    }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26