implement zalloc() - resolves #679 default tip

Sat, 24 May 2025 00:04:11 +0200

author
mike@uapl01.fritz.box
date
Sat, 24 May 2025 00:04:11 +0200
changeset 1330
33c95cfc088e
parent 1329
343eac5ac824

implement zalloc() - resolves #679

docs/Writerside/topics/allocator.h.md file | annotate | diff | comparison | revisions
src/allocator.c file | annotate | diff | comparison | revisions
src/cx/allocator.h file | annotate | diff | comparison | revisions
tests/test_allocator.c file | annotate | diff | comparison | revisions
--- a/docs/Writerside/topics/allocator.h.md	Fri May 23 14:00:24 2025 +0200
+++ b/docs/Writerside/topics/allocator.h.md	Sat May 24 00:04:11 2025 +0200
@@ -23,6 +23,8 @@
 
 void *cxMalloc(const CxAllocator *allocator, size_t n);
 
+void *cxZalloc(const CxAllocator *allocator, size_t n);
+
 void *cxCalloc(const CxAllocator *allocator,
         size_t nmemb, size_t size);
 
@@ -38,7 +40,9 @@
     
 void cxFree(const CxAllocator *allocator, void *mem);
 
-int cx_reallocate(void **mem, size_t size);
+void *cx_zalloc(size_t n);
+
+int cx_reallocate(void **mem, size_t n);
 
 int cx_reallocatearray(void **mem, size_t nmemb, size_t size);
 
@@ -50,6 +54,7 @@
 
 // Convenience macros that invokes above functions with the cxDefaultAllocator.
 #define cxMallocDefault(...)
+#define cxZallocDefault(...)
 #define cxCallocDefault(...)
 #define cxReallocDefault(...)
 #define cxReallocateDefault(...)
@@ -75,6 +80,9 @@
 most prominently that invocations of `cxFree()` with a `NULL`-pointer for `mem` are ignored
 instead of causing segfault error.
 
+The functions `cxZalloc()` and `cx_zalloc()` allocate memory and set every allocated byte to zero.
+The latter is merely a macro for stdlibc `calloc(1,n)`.
+
 Additionally, UCX provides the functions `cxReallocate()` and `cxReallocateArray()`, as well as
 their independent pendants `cx_reallocate()` and `cx_reallocatearray()`.
 All those functions solve the problem that a possible reallocation might fail,
--- a/src/allocator.c	Fri May 23 14:00:24 2025 +0200
+++ b/src/allocator.c	Sat May 24 00:04:11 2025 +0200
@@ -29,6 +29,7 @@
 #include "cx/allocator.h"
 
 #include <errno.h>
+#include <string.h>
 
 static void *cx_malloc_stdlib(
         cx_attr_unused void *d,
@@ -116,6 +117,17 @@
     return allocator->cl->malloc(allocator->data, n);
 }
 
+void *cxZalloc(
+        const CxAllocator *allocator,
+        size_t n
+) {
+    void *mem = allocator->cl->malloc(allocator->data, n);
+    if (mem != NULL) {
+        memset(mem, 0, n);
+    }
+    return mem;
+}
+
 void *cxRealloc(
         const CxAllocator *allocator,
         void *mem,
--- a/src/cx/allocator.h	Fri May 23 14:00:24 2025 +0200
+++ b/src/cx/allocator.h	Sat May 24 00:04:11 2025 +0200
@@ -228,6 +228,14 @@
     cx_reallocatearray_((void**)(mem), nmemb, size)
 
 /**
+ * Allocates memory and sets every byte to zero.
+ *
+ * @param n (@c size_t) the number of bytes
+ * @return (@c void*) a pointer to the allocated memory
+ */
+#define cx_zalloc(n) calloc(1, n)
+
+/**
  * Free a block allocated by this allocator.
  *
  * @note Freeing a block of a different allocator is undefined.
@@ -429,13 +437,33 @@
         size_t size
 );
 
-
+/**
+ * Allocate @p n bytes of memory and sets every byte to zero.
+ *
+ * @param allocator the allocator
+ * @param n the number of bytes
+ * @return a pointer to the allocated memory
+ */
+cx_attr_nodiscard
+cx_attr_nonnull
+cx_attr_malloc
+cx_attr_dealloc_ucx
+cx_attr_allocsize(2)
+cx_attr_export
+void *cxZalloc(
+        const CxAllocator *allocator,
+        size_t n
+);
 
 /**
  * Convenience macro that invokes cxMalloc() with the cxDefaultAllocator.
  */
 #define cxMallocDefault(...) cxMalloc(cxDefaultAllocator, __VA_ARGS__)
 /**
+ * Convenience macro that invokes cxZalloc() with the cxDefaultAllocator.
+ */
+#define cxZallocDefault(...) cxZalloc(cxDefaultAllocator, __VA_ARGS__)
+/**
  * Convenience macro that invokes cxCalloc() with the cxDefaultAllocator.
  */
 #define cxCallocDefault(...) cxCalloc(cxDefaultAllocator, __VA_ARGS__)
--- a/tests/test_allocator.c	Fri May 23 14:00:24 2025 +0200
+++ b/tests/test_allocator.c	Sat May 24 00:04:11 2025 +0200
@@ -46,6 +46,15 @@
     cxFree(cxStdlibAllocator, test);
 }
 
+CX_TEST(test_allocator_stdlib_zalloc) {
+    void *test = cxZalloc(cxStdlibAllocator, 16);
+    CX_TEST_DO {
+        CX_TEST_ASSERT(test != NULL);
+        CX_TEST_ASSERT(0 == memcmp(test, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16));
+    }
+    cxFree(cxStdlibAllocator, test);
+}
+
 CX_TEST(test_allocator_stdlib_calloc) {
     char *test = cxCalloc(cxStdlibAllocator, 8, 2);
     CX_TEST_DO {
@@ -110,6 +119,15 @@
     cxFreeDefault(test);
 }
 
+CX_TEST(test_allocator_default_zalloc) {
+    void *test = cxZallocDefault(16);
+    CX_TEST_DO {
+        CX_TEST_ASSERT(test != NULL);
+        CX_TEST_ASSERT(0 == memcmp(test, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16));
+    }
+    cxFreeDefault(test);
+}
+
 CX_TEST(test_allocator_default_calloc) {
     char *test = cxCallocDefault(8, 2);
     CX_TEST_DO {
@@ -270,12 +288,14 @@
     CxTestSuite *suite = cx_test_suite_new("allocator");
 
     cx_test_register(suite, test_allocator_stdlib_malloc);
+    cx_test_register(suite, test_allocator_stdlib_zalloc);
     cx_test_register(suite, test_allocator_stdlib_calloc);
     cx_test_register(suite, test_allocator_stdlib_realloc);
     cx_test_register(suite, test_allocator_stdlib_reallocarray);
     cx_test_register(suite, test_allocator_stdlib_reallocarray_overflow);
     cx_test_register(suite, test_allocator_stdlib_free);
     cx_test_register(suite, test_allocator_default_malloc);
+    cx_test_register(suite, test_allocator_default_zalloc);
     cx_test_register(suite, test_allocator_default_calloc);
     cx_test_register(suite, test_allocator_default_realloc);
     cx_test_register(suite, test_allocator_default_reallocarray);

mercurial