Branch
Hash :
7b089321
Author :
Date :
2025-01-01T09:24:36
maint: run 'make update-copyright'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
/* Memory allocation with expensive empty allocations.
Copyright (C) 2003, 2008, 2010-2025 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003,
based on prior work by Jim Meyering.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _EEALLOC_H
#define _EEALLOC_H
/* malloc (0) and realloc (NULL, 0) can return NULL even when memory
is available; see ISO C 23 sections 7.24.3.
When P is non-null realloc (P, 0) is worse, in that C23 says the
behavior is undefined whereas POSIX.1-2024 (which extends C17) says
that realloc (P, 0) when successful behaves like either (free (P),
errno = EINVAL, NULL), or like (free (P), malloc (1)) returning non-null
so long as you do not dereference the non-null pointer;
and glibc does not conform to POSIX as it behaves like (free (P), NULL).
There are similar issues with reallocarray.
This behavior is sometimes unwelcome, as it entails extra checking
to avoid confusing a zero-sized allocation with memory exhaustion,
and to avoid undefined behavior in C23.
This file provides malloc and realloc workalikes that consistently
treat zero sizes as requests for zero-sized allocations instead of
for null pointers. However, it does not provide workalikes for
related functions like aligned_alloc, calloc, and reallocarray. */
/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE, _GL_ATTRIBUTE_ALLOC_SIZE,
_GL_ATTRIBUTE_MALLOC. */
#if !_GL_CONFIG_H_INCLUDED
#error "Please include config.h first."
#endif
#include <stdlib.h>
#if defined __CHERI_PURE_CAPABILITY__
# include <cheri.h>
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef EEALLOC_INLINE
# define EEALLOC_INLINE _GL_INLINE
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if MALLOC_0_IS_NONNULL
# define eemalloc malloc
#else
EEALLOC_INLINE void *eemalloc (size_t n)
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1))
_GL_ATTRIBUTE_DEALLOC_FREE;
EEALLOC_INLINE void *
eemalloc (size_t n)
{
/* If n is zero, allocate a 1-byte block. */
size_t nx = n;
if (n == 0)
nx = 1;
void *ptr = malloc (nx);
# if defined __CHERI_PURE_CAPABILITY__
if (ptr != NULL)
ptr = cheri_bounds_set (ptr, n);
# endif
return ptr;
}
#endif
#if REALLOC_0_IS_NONNULL
# define eerealloc realloc
#else
EEALLOC_INLINE void *eerealloc (void *p, size_t n)
_GL_ATTRIBUTE_ALLOC_SIZE ((2));
EEALLOC_INLINE void *
eerealloc (void *p, size_t n)
{
/* Work around realloc glitch by treating a 0 size as if it were 1,
to avoid undefined behavior in strict C23 platforms,
and so that returning NULL is equivalent to failing. */
void *ptr = realloc (p, n ? n : 1);
# if defined __CHERI_PURE_CAPABILITY__
if (ptr != NULL)
ptr = cheri_bounds_set (ptr, n);
# endif
return ptr;
}
#endif
/* Maybe we should also define variants
eenmalloc (size_t n, size_t s) - behaves like eemalloc (n * s)
eezalloc (size_t n) - like eemalloc followed by memset 0
eecalloc (size_t n, size_t s) - like eemalloc (n * s) followed by memset 0
eenrealloc (void *p, size_t n, size_t s) - like eerealloc (p, n * s)
If this would be useful in your application. please speak up. */
#ifdef __cplusplus
}
#endif
_GL_INLINE_HEADER_END
#endif /* _EEALLOC_H */