libacfutils
A general purpose library of utility functions designed to make it easier to develop addons for the X-Plane flight simulator.
Loading...
Searching...
No Matches
safe_alloc.h
Go to the documentation of this file.
1/*
2 * CDDL HEADER START
3 *
4 * This file and its contents are supplied under the terms of the
5 * Common Development and Distribution License ("CDDL"), version 1.0.
6 * You may only use this file in accordance with the terms of version
7 * 1.0 of the CDDL.
8 *
9 * A full copy of the text of the CDDL should have accompanied this
10 * source. A copy of the CDDL is also available via the Internet at
11 * http://www.illumos.org/license/CDDL.
12 *
13 * CDDL HEADER END
14 */
15/*
16 * Copyright 2023 Saso Kiselkov. All rights reserved.
17 */
20#ifndef _ACF_UTILS_SAFE_ALLOC_H_
21#define _ACF_UTILS_SAFE_ALLOC_H_
22
23#include <errno.h>
24#include <string.h>
25#include <stdlib.h>
26
27#if IBM
28#include <malloc.h>
29#endif
30
31#if defined(__cplusplus) && __cplusplus >= 201703L
32#include <cstdlib>
33#endif
34
35#include "assert.h"
36#include "sysmacros.h"
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
55static inline void *
56safe_malloc(size_t size)
57{
58 void *p = malloc(size);
59 if (size > 0) {
60 VERIFY_MSG(p != NULL, "Cannot allocate %lu bytes: "
61 "out of memory", (long unsigned)size);
62 }
63 return (p);
64}
65
70static inline void *
71safe_calloc(size_t nmemb, size_t size)
72{
73 void *p = calloc(nmemb, size);
74 if (nmemb > 0 && size > 0) {
75 VERIFY_MSG(p != NULL, "Cannot allocate %lu bytes: "
76 "out of memory", (long unsigned)(nmemb * size));
77 }
78 return (p);
79}
80
85static inline void *
86safe_realloc(void *oldptr, size_t size)
87{
88 void *p = realloc(oldptr, size);
89 if (size > 0) {
90 VERIFY_MSG(p != NULL, "Cannot allocate %lu bytes: "
91 "out of memory", (long unsigned)size);
92 }
93 return (p);
94}
95
96#if !APL || __MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15
97#if IBM || __STDC_VERSION__ >= 201112L || __cplusplus >= 201703L || \
98 _POSIX_C_SOURCE >= 200112L || defined(__DOXYGEN__)
99
118static inline void *
119safe_aligned_malloc(size_t alignment, size_t size)
120{
121 void *p = NULL;
122 int err = 0;
123 ASSERT3U(alignment, >=, sizeof (void *));
124 ASSERT0(alignment ^ (1 << highbit64(alignment)));
125#if IBM
126 p = _aligned_malloc(size, alignment);
127 if (size > 0 && p == NULL)
128 err = ENOMEM;
129#elif __STDC_VERSION__ >= 201112L
130 p = aligned_alloc(alignment, size);
131 if (size > 0 && p == NULL)
132 err = ENOMEM;
133#elif __cplusplus >= 201703L
134 p = std::aligned_alloc(alignment, size);
135 if (size > 0 && p == NULL)
136 err = ENOMEM;
137#elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
138 err = posix_memalign(&p, alignment, size);
139#else /* !(__STDC_VERSION__ >= 201112L || _POSIX_C_SOURCE >= 200112L) */
140 VERIFY_FAIL();
141#endif /* !(__STDC_VERSION__ >= 201112L || _POSIX_C_SOURCE >= 200112L) */
142 VERIFY_MSG(err == 0, "Cannot allocate %lu bytes (align %lu): %s",
143 (long unsigned)size, (long unsigned)alignment, strerror(err));
144
145 return (p);
146}
147
166static inline void *
167safe_aligned_calloc(size_t alignment, size_t nmemb, size_t size)
168{
169 void *p = safe_aligned_malloc(alignment, nmemb * size);
170 memset(p, 0, size);
171 return (p);
172}
173
180static inline void
181aligned_free(void *ptr)
182{
183#if IBM
184 _aligned_free(ptr);
185#else
186 free(ptr);
187#endif
188}
189
190#endif \
191/* __STDC_VERSION__ || __cplusplus || IBM || _POSIX_C_SOURCE || __DOXYGEN__ */
192
193#endif /* !APL || CMAKE_OSX_DEPLOYMENT_TARGET >= MAC_OS_X_VERSION_10_15 */
194
200static inline char *
201safe_strdup(const char *str2)
202{
203 char *str;
204 size_t l;
205 ASSERT(str2 != NULL);
206 l = strlen(str2);
207 str = (char *)safe_malloc(l + 1);
208 memcpy(str, str2, l);
209 str[l] = '\0';
210 return (str);
211}
212
229static inline char *
230safe_append_realloc(char *buf, const char *str)
231{
232 char *newbuf;
233
234 ASSERT(str != NULL);
235 if (buf == NULL)
236 return (safe_strdup(str));
237 newbuf = (char *)safe_realloc(buf, strlen(buf) + strlen(str) + 1);
238 memcpy(&newbuf[strlen(newbuf)], str, strlen(str) + 1);
239 return (newbuf);
240}
241
253#define ZERO_FREE(ptr) \
254 do { \
255 NOT_TYPE_ASSERT(ptr, void *); \
256 NOT_TYPE_ASSERT(ptr, char *); \
257 if ((ptr) != NULL) \
258 memset((ptr), 0, sizeof (*(ptr))); \
259 free(ptr); \
260 } while (0)
264#define DESTROY_FREE(ptr) \
265 do { \
266 ZERO_FREE(ptr); \
267 (ptr) = NULL; \
268 } while (0)
269
275#define ZERO_FREE_N(ptr, num) \
276 do { \
277 NOT_TYPE_ASSERT(ptr, void *); \
278 if ((ptr) != NULL) \
279 memset((ptr), 0, sizeof (*(ptr)) * (num)); \
280 free(ptr); \
281 } while (0)
285#define DESTROY_FREE_N(ptr, num) \
286 do { \
287 ZERO_FREE_N((ptr), (num)); \
288 (ptr) = NULL; \
289 while (0)
290
296#define BZERO(data) memset((data), 0, sizeof (*(data)))
297
301#define SAFE_BZERO(data) \
302 do { \
303 if ((data) != NULL) \
304 BZERO(data); \
305 } while (0)
306
307#ifdef __cplusplus
308}
309#endif
310
311#endif /* _ACF_UTILS_SAFE_ALLOC_H_ */
#define VERIFY_FAIL()
Definition assert.h:160
#define ASSERT3U(x, op, y)
Definition assert.h:210
#define ASSERT(x)
Definition assert.h:208
#define ASSERT0(x)
Definition assert.h:213
#define VERIFY_MSG(x, fmt,...)
Definition assert.h:91
static char * safe_append_realloc(char *buf, const char *str)
Definition safe_alloc.h:230
static void aligned_free(void *ptr)
Definition safe_alloc.h:181
static void * safe_realloc(void *oldptr, size_t size)
Definition safe_alloc.h:86
static void * safe_aligned_calloc(size_t alignment, size_t nmemb, size_t size)
Definition safe_alloc.h:167
static void * safe_aligned_malloc(size_t alignment, size_t size)
Definition safe_alloc.h:119
static char * safe_strdup(const char *str2)
Definition safe_alloc.h:201
static void * safe_calloc(size_t nmemb, size_t size)
Definition safe_alloc.h:71
static void * safe_malloc(size_t size)
Definition safe_alloc.h:56