Home | History | Annotate | Line # | Download | only in libiberty
      1 /* memory allocation routines with error checking.
      2    Copyright (C) 1989-2025 Free Software Foundation, Inc.
      3 
      4 This file is part of the libiberty library.
      5 Libiberty is free software; you can redistribute it and/or
      6 modify it under the terms of the GNU Library General Public
      7 License as published by the Free Software Foundation; either
      8 version 2 of the License, or (at your option) any later version.
      9 
     10 Libiberty is distributed in the hope that it will be useful,
     11 but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13 Library General Public License for more details.
     14 
     15 You should have received a copy of the GNU Library General Public
     16 License along with libiberty; see the file COPYING.LIB.  If
     17 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
     18 Boston, MA 02110-1301, USA.  */
     19 
     20 /*
     21 
     22 @deftypefn Replacement void* xmalloc (size_t)
     23 
     24 Allocate memory without fail.  If @code{malloc} fails, this will print
     25 a message to @code{stderr} (using the name set by
     26 @code{xmalloc_set_program_name},
     27 if any) and then call @code{xexit}.  Note that it is therefore safe for
     28 a program to contain @code{#define malloc xmalloc} in its source.
     29 
     30 @end deftypefn
     31 
     32 @deftypefn Replacement void* xrealloc (void *@var{ptr}, size_t @var{size})
     33 Reallocate memory without fail.  This routine functions like @code{realloc},
     34 but will behave the same as @code{xmalloc} if memory cannot be found.
     35 
     36 @end deftypefn
     37 
     38 @deftypefn Replacement void* xcalloc (size_t @var{nelem}, size_t @var{elsize})
     39 
     40 Allocate memory without fail, and set it to zero.  This routine functions
     41 like @code{calloc}, but will behave the same as @code{xmalloc} if memory
     42 cannot be found.
     43 
     44 @end deftypefn
     45 
     46 @deftypefn Replacement void xmalloc_set_program_name (const char *@var{name})
     47 
     48 You can use this to set the name of the program used by
     49 @code{xmalloc_failed} when printing a failure message.
     50 
     51 @end deftypefn
     52 
     53 @deftypefn Replacement void xmalloc_failed (size_t)
     54 
     55 This function is not meant to be called by client code, and is listed
     56 here for completeness only.  If any of the allocation routines fail, this
     57 function will be called to print an error message and terminate execution.
     58 
     59 @end deftypefn
     60 
     61 */
     62 
     63 #ifdef HAVE_CONFIG_H
     64 #include "config.h"
     65 #endif
     66 #include "ansidecl.h"
     67 #include "libiberty.h"
     68 #include "environ.h"
     69 
     70 #include <stdio.h>
     71 
     72 #include <stddef.h>
     73 
     74 #if VMS
     75 #include <stdlib.h>
     76 #include <unixlib.h>
     77 #else
     78 /* For systems with larger pointers than ints, these must be declared.  */
     79 #  if HAVE_STDLIB_H && HAVE_UNISTD_H && HAVE_DECL_MALLOC \
     80       && HAVE_DECL_REALLOC && HAVE_DECL_CALLOC && HAVE_DECL_SBRK
     81 #    include <stdlib.h>
     82 #    include <unistd.h>
     83 #  else
     84 #    ifdef __cplusplus
     85 extern "C" {
     86 #    endif /* __cplusplus */
     87 void *malloc (size_t);
     88 void *realloc (void *, size_t);
     89 void *calloc (size_t, size_t);
     90 #ifdef HAVE_SBRK
     91 void *sbrk (ptrdiff_t);
     92 #endif
     93 #    ifdef __cplusplus
     94 }
     95 #    endif /* __cplusplus */
     96 #  endif /* HAVE_STDLIB_H ...  */
     97 #endif /* VMS */
     98 
     99 /* The program name if set.  */
    100 static const char *name = "";
    101 
    102 #ifdef HAVE_SBRK
    103 /* The initial sbrk, set when the program name is set. Not used for win32
    104    ports other than cygwin32.  */
    105 static char *first_break = NULL;
    106 #endif /* HAVE_SBRK */
    107 
    108 void
    109 xmalloc_set_program_name (const char *s)
    110 {
    111   name = s;
    112 #ifdef HAVE_SBRK
    113   /* Win32 ports other than cygwin32 don't have brk() */
    114   if (first_break == NULL)
    115     first_break = (char *) sbrk (0);
    116 #endif /* HAVE_SBRK */
    117 }
    118 
    119 void
    120 xmalloc_failed (size_t size)
    121 {
    122 #ifdef HAVE_SBRK
    123   size_t allocated;
    124 
    125   if (first_break != NULL)
    126     allocated = (char *) sbrk (0) - first_break;
    127   else
    128     allocated = (char *) sbrk (0) - (char *) &environ;
    129   fprintf (stderr,
    130 	   "\n%s%sout of memory allocating %lu bytes after a total of %lu bytes\n",
    131 	   name, *name ? ": " : "",
    132 	   (unsigned long) size, (unsigned long) allocated);
    133 #else /* HAVE_SBRK */
    134   fprintf (stderr,
    135 	   "\n%s%sout of memory allocating %lu bytes\n",
    136 	   name, *name ? ": " : "",
    137 	   (unsigned long) size);
    138 #endif /* HAVE_SBRK */
    139   xexit (1);
    140 }
    141 
    142 void *
    143 xmalloc (size_t size)
    144 {
    145   void *newmem;
    146 
    147   if (size == 0)
    148     size = 1;
    149   newmem = malloc (size);
    150   if (!newmem)
    151     xmalloc_failed (size);
    152 
    153   return (newmem);
    154 }
    155 
    156 void *
    157 xcalloc (size_t nelem, size_t elsize)
    158 {
    159   void *newmem;
    160 
    161   if (nelem == 0 || elsize == 0)
    162     nelem = elsize = 1;
    163 
    164   newmem = calloc (nelem, elsize);
    165   if (!newmem)
    166     xmalloc_failed (nelem * elsize);
    167 
    168   return (newmem);
    169 }
    170 
    171 void *
    172 xrealloc (void *oldmem, size_t size)
    173 {
    174   void *newmem;
    175 
    176   if (size == 0)
    177     size = 1;
    178   if (!oldmem)
    179     newmem = malloc (size);
    180   else
    181     newmem = realloc (oldmem, size);
    182   if (!newmem)
    183     xmalloc_failed (size);
    184 
    185   return (newmem);
    186 }
    187