commit 10821efb8b7d9688408de07f4dbd0078ed6ec2fa
parent 18f833e9a6f8aae2b678ff9a749e9ec0c75eca3f
Author: Robert Russell <robertrussell.72001@gmail.com>
Date: Wed, 7 Sep 2022 14:44:22 -0700
Change realloc function signatures
On allocation failure, realloc returns NULL and does not touch
the given memory block. Thus, writing simply
p = realloc(p, newsize);
is wrong, because we lose the pointer to the memory block on
failure. Instead, we must write
void *q = realloc(p, newsize);
if (!q)
handle_error();
p = q;
which is a bit cumbersome. With the new function signatures,
we simply write
if (r_realloc(&p, newsize) < 0)
handle_error();
or
r_erealloc(&p, newsize);
Diffstat:
4 files changed, 51 insertions(+), 41 deletions(-)
diff --git a/inc/rcx/alloc.h b/inc/rcx/alloc.h
@@ -14,17 +14,17 @@ void *r_alloc(usize size); /* aka malloc */
void *r_allocz(usize size);
void *r_allocn(usize len, usize size);
void *r_allocnz(usize len, usize size); /* aka calloc */
-void *r_realloc(void *p, usize size);
-void *r_reallocz(void *p, usize osize, usize nsize);
-void *r_reallocn(void *p, usize len, usize size);
-void *r_reallocnz(void *p, usize olen, usize nlen, usize size);
+int r_realloc(void **p, usize size);
+int r_reallocz(void **p, usize osize, usize nsize);
+int r_reallocn(void **p, usize len, usize size);
+int r_reallocnz(void **p, usize olen, usize nlen, usize size);
void *r_ealloc(usize size);
void *r_eallocz(usize size);
void *r_eallocn(usize len, usize size);
void *r_eallocnz(usize len, usize size);
-void *r_erealloc(void *p, usize size);
-void *r_ereallocz(void *p, usize osize, usize nsize);
-void *r_ereallocn(void *p, usize len, usize size);
-void *r_ereallocnz(void *p, usize olen, usize nlen, usize size);
+void r_erealloc(void **p, usize size);
+void r_ereallocz(void **p, usize osize, usize nsize);
+void r_ereallocn(void **p, usize len, usize size);
+void r_ereallocnz(void **p, usize olen, usize nlen, usize size);
void free(void *p);
diff --git a/inc/rcx/deque.h b/inc/rcx/deque.h
@@ -59,23 +59,21 @@ int R_DEQUE_METHOD(reserve,##__VA_ARGS__)(D *d, usize n) { \
if (ncap == 0) \
return -1; /* Overflow */ \
} \
- T *narr = R_DEQUE_REALLOCN(d->arr, ncap, sizeof *narr); \
- if (!narr) \
+ if (R_DEQUE_REALLOCN(&d->arr, ncap, sizeof *d->arr) < 0) \
return -1; \
if (d->l == d->cap) { \
d->l = ncap; /* Maintain invariant for empty deques */ \
} else if (d->r <= d->l) { \
/* Move as little as possible */ \
if (d->r <= d->cap - d->l) { \
- memcpy(&narr[d->cap], &narr[0], d->r * sizeof *narr); \
+ memcpy(&d->arr[d->cap], &d->arr[0], d->r * sizeof *d->arr); \
d->r += d->cap; \
} else { \
usize m = d->cap - d->l; \
- memcpy(&narr[ncap-m], &narr[d->l], m * sizeof *narr); \
+ memcpy(&d->arr[ncap-m], &d->arr[d->l], m * sizeof *d->arr); \
d->l = ncap - m; \
} \
} \
- d->arr = narr; \
d->cap = ncap; \
return 0; \
} \
diff --git a/inc/rcx/vector.h b/inc/rcx/vector.h
@@ -59,8 +59,8 @@ int R_VECTOR_METHOD(resize,##__VA_ARGS__)(T **v, usize cap) { \
errno = ENOMEM; \
return -1; \
} \
- h = R_VECTOR_REALLOC(h, sizeof *h + arrsize); \
- if (!h) return -1; \
+ if (R_VECTOR_REALLOC(&h, sizeof *h + arrsize) < 0) \
+ return -1; \
h->len = MIN(len, cap); \
h->cap = cap; \
*v = (void *)(h + 1); \
diff --git a/src/alloc.c b/src/alloc.c
@@ -32,51 +32,63 @@ r_allocnz(usize len, usize size) {
return calloc(len, size);
}
-void *
-r_realloc(void *p, usize size) {
- return realloc(p, size);
+int
+r_realloc(void **p, usize size) {
+ void *q = realloc(*p, size);
+ if (!q) return -1;
+ *p = q;
+ return 0;
}
-void *
-r_reallocz(void *p, usize osize, usize nsize) {
- p = r_realloc(p, nsize);
- if (p && nsize > osize)
- memset((char *) p + osize, 0, nsize - osize);
- return p;
+int
+r_reallocz(void **p, usize osize, usize nsize) {
+ int ret = r_realloc(p, nsize);
+ if (ret == 0 && nsize > osize)
+ memset((char *)*p + osize, 0, nsize - osize);
+ return ret;
}
-void *
-r_reallocn(void *p, usize len, usize size) {
+int
+r_reallocn(void **p, usize len, usize size) {
if (r_mul_will_overflow_(len, size)) {
errno = ENOMEM;
- return 0;
+ return -1;
}
return r_realloc(p, len * size);
}
-void *
-r_reallocnz(void *p, usize olen, usize nlen, usize size) {
+int
+r_reallocnz(void **p, usize olen, usize nlen, usize size) {
if (r_mul_will_overflow_(nlen, size)) {
errno = ENOMEM;
- return 0;
+ return -1;
}
return r_reallocz(p, olen * size, nlen * size);
}
-#define EALLOC(name, ...)\
- void *r_e##name(__VA_ARGS__) {\
- void *q = r_##name(EALLOC_AUX
+#define EALLOC(mods, ...)\
+ void *r_ealloc##mods(__VA_ARGS__) {\
+ void *q = r_alloc##mods(EALLOC_AUX
#define EALLOC_AUX(...)\
__VA_ARGS__);\
if (!q) r_fatalf("allocation failure");\
return q;\
}
-EALLOC(alloc, usize size)(size)
-EALLOC(allocz, usize size)(size)
-EALLOC(allocn, usize len, usize size)(len, size)
-EALLOC(allocnz, usize len, usize size)(len, size)
-EALLOC(realloc, void *p, usize size)(p, size)
-EALLOC(reallocz, void *p, usize osize, usize nsize)(p, osize, nsize)
-EALLOC(reallocn, void *p, usize len, usize size)(p, len, size)
-EALLOC(reallocnz, void *p, usize olen, usize nlen, usize size)(p, olen, nlen, size)
+EALLOC(, usize size)(size)
+EALLOC(z, usize size)(size)
+EALLOC(n, usize len, usize size)(len, size)
+EALLOC(nz, usize len, usize size)(len, size)
+
+#define EREALLOC(mods, ...)\
+ void r_erealloc##mods(void **p, __VA_ARGS__) {\
+ int ret = r_realloc##mods(p, EREALLOC_AUX
+#define EREALLOC_AUX(...)\
+ __VA_ARGS__);\
+ if (ret < 0) r_fatalf("allocation failure");\
+ }
+
+EREALLOC(, usize size)(size)
+EREALLOC(z, usize osize, usize nsize)(osize, nsize)
+EREALLOC(n, usize len, usize size)(len, size)
+EREALLOC(nz, usize olen, usize nlen, usize size)(olen, nlen, size)