I wrote a bunch of functions and macros for safer and simpler allocation. They are documented in their files.
Disclaimer:
The library requires POSIX extensions, GCC extensions, and LIBBSD extensions, but if someone wants to make it portable, it shouldn't be difficult to get rid of the extensions I used. But to me, they are of great help and make my life much easier.
I use goto
because it is cleaner to me (the way I use it), but if someone wants to get rid of it, it should be easy.
I acknowledge some inconsistency in the parameter nmemb
which is sometimes ptrdiff_t
and some others size_t
. I would like it to always be ptrdiff_t
, but in the macros that call standard functions (instead of mine) those standard functions accept size_t
, and the code to reject negative values of ptrdiff_t
inside a macro would make the macros too long and dangerous. In functions and in macros that call functions of mine, I consistently use ptrdiff_t
.
libalx/base/stdlib/alloc/README.rst
:
<libalx/base/stdlib/alloc/>
============================
The following functions are added to the C / POSIX / GNU / BSD allocation
functions (some of them may be implemented as macros; only when necessary).
1) Headers
----------
.. code-block:: c
<libalx/base/stdlib/alloc/callocs.h>
<libalx/base/stdlib/alloc/callocs.hpp>
<libalx/base/stdlib/alloc/mallocarray.h>
<libalx/base/stdlib/alloc/mallocarray.hpp>
<libalx/base/stdlib/alloc/mallocarrays.h>
<libalx/base/stdlib/alloc/mallocarrays.hpp>
<libalx/base/stdlib/alloc/mallocs.h>
<libalx/base/stdlib/alloc/mallocs.hpp>
<libalx/base/stdlib/alloc/reallocarrayf.h>
<libalx/base/stdlib/alloc/reallocarrayf.hpp>
<libalx/base/stdlib/alloc/reallocarrayfs.h>
<libalx/base/stdlib/alloc/reallocarrayfs.hpp>
<libalx/base/stdlib/alloc/reallocarrays.h>
<libalx/base/stdlib/alloc/reallocarrays.hpp>
<libalx/base/stdlib/alloc/reallocfs.h>
<libalx/base/stdlib/alloc/reallocfs.hpp>
<libalx/base/stdlib/alloc/reallocs.h>
<libalx/base/stdlib/alloc/reallocs.hpp>
2) Functions
------------
.. code-block:: c
[[gnu::nonnull]]
int callocs(type **restrict ptr, size_t nmemb);
[[gnu::malloc]] [[gnu::warn_unused_result]]
void *mallocarray(ptrdiff_t nmemb, size_t size);
[[gnu::nonnull]] [[gnu::warn_unused_result]]
int mallocarrays(type **restrict ptr, ptrdiff_t nmemb);
[[gnu::nonnull]] [[gnu::warn_unused_result]]
int mallocs(void **restrict ptr, size_t size);
[[gnu::warn_unused_result]]
void *reallocarrayf(void *ptr, ptrdiff_t nmemb, size_t size);
[[gnu::nonnull]] [[gnu::warn_unused_result]]
int reallocarrayfs(type **restrict ptr, ptrdiff_t nmemb);
[[gnu::nonnull]][[gnu::warn_unused_result]]
int reallocarrays(type **restrict ptr, ptrdiff_t nmemb);
[[gnu::nonnull]] [[gnu::warn_unused_result]]
int reallocfs(void **restrict ptr, size_t size);
[[gnu::nonnull]] [[gnu::warn_unused_result]]
int reallocs(void **restrict ptr, size_t size);
To be able to use any of those functions, the corresponding headers should be
included.
3) When to use each of the functions
------------------------------------
Functions ending in ``s`` should always be preferred.
Reallocation functions ending in ``f`` (or ``fs``) free the memory upon
failure to ease error handling.
Functions containing ``array`` (and ``callocs()``) should be used when
allocating arrays, or single elements (arrays of size 1). The other funtions
should be used when and only when dealing with buffers of bytes.
4) More info
------------
For more detailed documentation about each of the functions, read the
corresponding headers.
libalx/base/stdlib/alloc/callocs.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/callocs.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::nonnull]]
* int callocs(type **restrict ptr, size_t nmemb);
*
* Safe & simple wrapper for `calloc()`.
*
* Features:
* - Safely computes the element size (second argument to `calloc()`)
* so the user can't make mistakes.
* - Returns non-zero on error.
* - Doesn't cast
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/callocs.h>
*
* int *arr;
*
* if (callocs(&arr, 7)) // int arr[7];
* goto err;
*
* // `arr` has been succesfully allocated here
* free(arr);
* err:
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <stdlib.h>
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/*
* callocs()
*
* ptr: Memory will be allocated, and a pointer to it will be stored
* in *ptr.
* nmemb: Number of elements in the array.
*
* return:
* 0: OK.
* != 0: Failed.
*/
#define alx_callocs(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
\
*ptr_ = calloc(nmemb, sizeof(**ptr_)); \
\
!(*ptr_); \
} \
)
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
#define callocs(ptr, nmemb) alx_callocs(ptr, nmemb)
#endif
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* prototypes ***********************************************************
******************************************************************************/
/******************************************************************************
******* inline ***************************************************************
******************************************************************************/
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/mallocarray.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/mallocarray.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::malloc]] [[gnu::warn_unused_result]]
* void *mallocarray(ptrdiff_t nmemb, size_t size);
*
* Almost equivalent to `reallocarray(NULL, nmemb, size)`.
*
* Features:
* - It fails safely if (nmemb < 0). With `reallocarray()` the array would be
* be allocated (it uses `size_t` instead of `ptrdiff_t`), and it's usage
* would likely produce undefined behavior.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/mallocarray.h>
*
* int *arr;
*
* arr = mallocarray(7, sizeof(*arr)); // int arr[7];
* if (!arr)
* goto err;
*
* // `arr` has been succesfully allocated here
* free(arr);
* err:
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* prototypes ***********************************************************
******************************************************************************/
/*
* mallocarray()
*
* nmemb: Number of elements in the array.
* size: Size of each element in the array.
*
* return:
* != NULL: OK.
* NULL: Failed.
*/
__attribute__((malloc, warn_unused_result))
inline
void *alx_mallocarray (ptrdiff_t nmemb, size_t size);
/******************************************************************************
******* static inline ********************************************************
******************************************************************************/
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
__attribute__((always_inline, malloc, warn_unused_result))
static inline
void *mallocarray (ptrdiff_t nmemb, size_t size)
{
return alx_mallocarray(nmemb, size);
}
#endif
/******************************************************************************
******* inline ***************************************************************
******************************************************************************/
inline
void *alx_mallocarray (ptrdiff_t nmemb, size_t size)
{
if (nmemb < 0)
goto ovf;
return reallocarray(NULL, nmemb, size);
ovf:
errno = ENOMEM;
return NULL;
}
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/mallocarrays.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/mallocarrays.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::nonnull]] [[gnu::warn_unused_result]]
* int mallocarrays(type **restrict ptr, ptrdiff_t nmemb);
*
* Safe & simple wrapper for `mallocarray()`.
*
* Features:
* - Safely computes the element size (second argument to `mallocarray()`)
* so the user can't make mistakes.
* - Returns non-zero on error.
* - Doesn't cast
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/mallocarrays.h>
*
* int *arr;
*
* if (mallocarrays(&arr, 7)) // int arr[7];
* goto err;
*
* // `arr` has been succesfully allocated here
* free(arr);
* err:
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "libalx/base/stdlib/alloc/mallocarray.h"
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/*
* mallocarrays()
*
* ptr: Memory will be allocated, and a pointer to it will be stored
* in *ptr.
* nmemb: Number of elements in the array.
*
* return:
* 0: OK.
* != 0: Failed.
*/
#define alx_mallocarrays(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
\
*ptr_ = alx_mallocarray(nmemb, sizeof(**ptr_)); \
\
!(*ptr_); \
} \
)
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
#define mallocarrays(ptr, nmemb) alx_mallocarrays(ptr, nmemb)
#endif
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* function prototypes **************************************************
******************************************************************************/
/******************************************************************************
******* inline functions *****************************************************
******************************************************************************/
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/mallocs.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/mallocs.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::nonnull]] [[gnu::warn_unused_result]]
* int mallocs(void **restrict ptr, size_t size);
*
* Safe & simple wrapper for `malloc()`.
* To be used for generic buffers of bytes, and not for arrays (use
* `mallocarray()` family of functions for that purpose).
*
* Features:
* - Returns non-zero on error.
* - Doesn't cast
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/mallocs.h>
*
* char *buf;
*
* if (mallocs(&buf, 7)) // char buf[7];
* goto err;
*
* // `buf` has been succesfully allocated here
* free(buf);
* err:
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <stddef.h>
#include <stdlib.h>
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* prototypes ***********************************************************
******************************************************************************/
/*
* mallocs()
*
* ptr: Memory will be allocated, and a pointer to it will be stored
* in *ptr.
* size: Size of the buffer (in bytes).
*
* return:
* 0: OK.
* != 0: Failed.
*/
__attribute__((nonnull, warn_unused_result))
inline
int alx_mallocs (void **restrict ptr, size_t size);
/******************************************************************************
******* static inline ********************************************************
******************************************************************************/
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
__attribute__((always_inline, nonnull, warn_unused_result))
static inline
int mallocs (void **restrict ptr, size_t size)
{
return alx_mallocs(ptr, size);
}
#endif
/******************************************************************************
******* inline ***************************************************************
******************************************************************************/
inline
int alx_mallocs (void **restrict ptr, size_t size)
{
*ptr = malloc(size);
return !(*ptr);
}
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/reallocarrayf.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/reallocarrayf.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::warn_unused_result]]
* void *reallocarrayf(void *ptr, ptrdiff_t nmemb, size_t size);
*
* Almost equivalent to `reallocarray()`.
*
* Features:
* - Upon failure, the passed pointer is freed, to ease error handling and to
* avoid memory leaks.
* - It fails safely if (nmemb < 0). With `reallocarray()` the array would be
* be allocated (it uses `size_t` instead of `ptrdiff_t`), and it's usage
* would likely produce undefined behavior.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/reallocarrayf.h>
*
* int *arr;
*
* arr = mallocarray(5, sizeof(*arr); // int arr[5];
* arr = reallocarrayf(arr, 7, sizeof(*arr)); // int arr[7];
* if (!arr)
* goto err;
*
* // `arr` has been succesfully reallocated here
* free(arr);
* err:
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
/******************************************************************************
******* _Static_assert *******************************************************
******************************************************************************/
_Static_assert(sizeof(size_t) == sizeof(ptrdiff_t),
"sizeof(size_t) != sizeof(ptrdiff_t)");
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* prototypes ***********************************************************
******************************************************************************/
/*
* reallocarrayf()
*
* ptr: Pointer to allocated memory (or NULL).
* nmemb: Number of elements in the array.
* size: Size of each element in the array.
*
* return:
* != NULL: OK.
* NULL: Failed.
*/
__attribute__((warn_unused_result))
inline
void *alx_reallocarrayf (void *ptr, ptrdiff_t nmemb, size_t size);
/******************************************************************************
******* static inline ********************************************************
******************************************************************************/
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
__attribute__((always_inline, warn_unused_result))
static inline
void *reallocarrayf (void *ptr, ptrdiff_t nmemb, size_t size)
{
return alx_reallocarrayf(ptr, nmemb, size);
}
#endif
/******************************************************************************
******* inline ***************************************************************
******************************************************************************/
inline
void *alx_reallocarrayf (void *ptr, ptrdiff_t nmemb, size_t size)
{
if (!size)
goto out;
if (nmemb < 0)
goto ovf;
if ((size_t)nmemb > (SIZE_MAX / size))
goto ovf;
return reallocf(ptr, size * (size_t)nmemb);
ovf:
errno = ENOMEM;
out:
free(ptr);
return NULL;
}
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/reallocarrayfs.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/reallocarrayfs.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::nonnull]] [[gnu::warn_unused_result]]
* int reallocarrayfs(type **restrict ptr, ptrdiff_t nmemb);
*
* Safe & simple wrapper for `reallocarrayf()`.
*
* Features:
* - Safely computes the element size (second argument to `reallocarrayf()`)
* so the user can't make mistakes.
* - Returns non-zero on error.
* - Doesn't cast.
* - Upon failure, the passed pointer is freed, to ease error handling and to
* avoid memory leaks.
* - It fails safely if (nmemb < 0). With `reallocarray()` the array would be
* be allocated (it uses `size_t` instead of `ptrdiff_t`), and it's usage
* would likely produce undefined behavior.
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/reallocarrayfs.h>
*
* int *arr;
*
* if (mallocarrays(&arr, 5)) // int arr[5];
* goto err;
* if (reallocarrayfs(&arr, 7)) // int arr[7];
* goto err;
*
* // `arr` has been succesfully reallocated here
* free(arr);
* err:
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include "libalx/base/stdlib/alloc/reallocarrayf.h"
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/*
* reallocarrayfs()
*
* ptr: Pointer to a pointer to the memory to be reallocated.
* A pointer to the reallocated memory will be stored
* in *ptr.
* nmemb: Number of elements in the array.
*
* return:
* 0: OK.
* != 0: Failed.
*/
#define alx_reallocarrayfs(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
\
*ptr_ = alx_reallocarrayf(*ptr_, nmemb, sizeof(**ptr_)); \
\
!(*ptr_); \
} \
)
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
#define reallocarrayfs(ptr, nmemb) alx_reallocarrayfs(ptr, nmemb)
#endif
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* function prototypes **************************************************
******************************************************************************/
/******************************************************************************
******* inline functions *****************************************************
******************************************************************************/
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/reallocarrays.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/reallocarrays.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::nonnull]][[gnu::warn_unused_result]]
* int reallocarrays(type **restrict ptr, size_t nmemb);
*
* Safe & simple wrapper for `reallocarray()`.
*
* Features:
* - Safely computes the element size (second argument to `reallocarray()`)
* so the user can't make mistakes.
* - Returns non-zero on error.
* - Doesn't cast.
* - Upon failure, the pointer is untouched (no memory leak).
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/reallocarrays.h>
*
* int *arr;
*
* if (mallocarrays(&arr, 5)) // int arr[5];
* goto err;
* if (reallocarrays(&arr, 7)) // int arr[7];
* goto err;
*
* // `arr` has been succesfully reallocated here
* err:
* free(arr);
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <stdlib.h>
#include "libalx/base/stdlib/alloc/reallocs.h"
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/*
* reallocarrays()
*
* ptr: Pointer to a pointer to the memory to be reallocated.
* A pointer to the reallocated memory will be stored
* in *ptr.
* nmemb: Number of elements in the array.
*
* return:
* 0: OK.
* != 0: Failed.
*/
#define alx_reallocarrays(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
__auto_type nmemb_ = (nmemb); \
void *vp_; \
\
vp_ = reallocarray(*ptr_, nmemb_, sizeof(**ptr_)); \
\
alx_reallocs__(ptr_, vp_, nmemb_); \
} \
)
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
#define reallocarrays(ptr, nmemb) alx_reallocarrays(ptr, nmemb)
#endif
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* function prototypes **************************************************
******************************************************************************/
/******************************************************************************
******* inline functions *****************************************************
******************************************************************************/
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/reallocfs.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/reallocfs.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::nonnull]] [[gnu::warn_unused_result]]
* int reallocfs(void **restrict ptr, size_t size);
*
* Safe & simple wrapper for `reallocf()`.
* To be used for generic buffers of bytes, and not for arrays (use
* `reallocarray()` family of functions for that purpose).
*
* Features:
* - Returns non-zero on error.
* - Doesn't cast.
* - Upon failure, the passed pointer is freed, to ease error handling and to
* avoid memory leaks.
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/reallocfs.h>
*
* char *buf;
*
* if (mallocs(&buf, 5)) // char buf[5];
* goto err;
* if (reallocfs(&buf, 7)) // char buf[7];
* goto err;
*
* // `buf` has been succesfully reallocated here
* free(buf);
* err:
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <stddef.h>
#include <stdlib.h>
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* prototypes ***********************************************************
******************************************************************************/
/*
* reallocfs()
*
* ptr: Pointer to a pointer to the memory to be reallocated.
* A pointer to the reallocated memory will be stored
* in *ptr.
* size: Size of the buffer (in bytes).
*
* return:
* 0: OK.
* != 0: Failed.
*/
__attribute__((nonnull, warn_unused_result))
inline
int alx_reallocfs (void **restrict ptr, size_t size);
/******************************************************************************
******* static inline ********************************************************
******************************************************************************/
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
__attribute__((always_inline, nonnull, warn_unused_result))
static inline
int reallocfs (void **restrict ptr, size_t size)
{
return alx_reallocfs(ptr, size);
}
#endif
/******************************************************************************
******* inline ***************************************************************
******************************************************************************/
inline
int alx_reallocfs (void **restrict ptr, size_t size)
{
*ptr = reallocf(*ptr, size);
return !*ptr;
}
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
libalx/base/stdlib/alloc/reallocs.h
:
/******************************************************************************
******* include guard ********************************************************
******************************************************************************/
#pragma once /* libalx/base/stdlib/alloc/reallocs.h */
/******************************************************************************
******* about ****************************************************************
******************************************************************************/
/*
* [[gnu::nonnull]] [[gnu::warn_unused_result]]
* int reallocs(void **restrict ptr, size_t size);
*
* Safe & simple wrapper for `reallocf()`.
* To be used for generic buffers of bytes, and not for arrays (use
* `reallocarray()` family of functions for that purpose).
*
* Features:
* - Returns non-zero on error.
* - Doesn't cast.
* - Upon failure, the pointer is untouched (no memory leak).
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* example:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/reallocs.h>
*
* char *buf;
*
* if (mallocs(&buf, 5)) // char buf[5];
* goto err;
* if (reallocs(&buf, 7)) // char buf[7];
* goto err;
*
* // `buf` has been succesfully reallocated here
* err:
* free(buf);
* // No memory leaks
*/
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
/******************************************************************************
******* enum *****************************************************************
******************************************************************************/
/******************************************************************************
******* struct / union *******************************************************
******************************************************************************/
/******************************************************************************
******* prototypes ***********************************************************
******************************************************************************/
/*
* reallocs()
*
* ptr: Pointer to a pointer to the memory to be reallocated.
* A pointer to the reallocated memory will be stored
* in *ptr.
* size: Size of the buffer (in bytes).
*
* return:
* 0: OK.
* != 0: Failed.
*/
__attribute__((nonnull, warn_unused_result))
inline
int alx_reallocs (void **restrict ptr, size_t size);
/*
* alx_reallocs__()
*
* This function safely assigns the result of a reallocation to the pointer
* provided. If the reallocation failed, this function doesn't assign the
* pointer, and keeps the old one. This function is only to be used within
* this library, and should not be called directly by the user.
*
* ptr: Pointer to a pointer to the memory to be reallocated.
* A pointer to the reallocated memory will be stored
* in *ptr.
* vp: Result of `realloc()`.
* size: `size` passed to `realloc()`.
*
* return:
* 0: OK.
* != 0: Reallocation failed.
*/
__attribute__((nonnull(1), warn_unused_result))
inline
int alx_reallocs__ (void **restrict ptr, void *restrict vp, size_t size);
/******************************************************************************
******* static inline ********************************************************
******************************************************************************/
/* Rename without alx_ prefix */
#if defined(ALX_NO_PREFIX)
__attribute__((always_inline, nonnull, warn_unused_result))
static inline
int reallocs (void **restrict ptr, size_t size)
{
return alx_reallocs(ptr, size);
}
#endif
/******************************************************************************
******* inline ***************************************************************
******************************************************************************/
inline
int alx_reallocs (void **restrict ptr, size_t size)
{
void *vp;
vp = realloc(*ptr, size);
return alx_reallocs__(ptr, vp, size);
}
inline
int alx_reallocs__ (void **restrict ptr, void *restrict vp, size_t size)
{
bool failed;
failed = !vp && size;
if (!failed)
*ptr = vp;
return failed;
}
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/
Any comments?