David Allan wrote:
Allocates a buffer containing a struct with variable sized array as
the last member, useful for some ioctl and other APIs that return data in this way.
---
src/util/memory.h | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/src/util/memory.h b/src/util/memory.h
index fc9e6c1..e7effd6 100644
--- a/src/util/memory.h
+++ b/src/util/memory.h
@@ -76,6 +76,24 @@ void virFree(void *ptrptr);
#define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count))
/**
+ * VIR_ALLOC_VAR:
+ * @ptr: pointer to hold address of allocated memory
+ * @type: element type of trailing array
+ * @count: number of array elements to allocate
+ *
+ * Allocate sizeof(*ptr) bytes plus an array of 'count' elements, each
+ * sizeof('type'). This sort of allocation is useful for receiving
+ * the data of certain ioctls and other APIs which return a struct in
+ * which the last element is an array of undefined length. The caller
+ * of this type of API is expected to know the length of the array
+ * that will be returned and allocate a suitable buffer to contain the
+ * returned data.
+ *
+ * Returns -1 on failure, 0 on success
Hi Dave,
This sounds like what at least gcc calls flexible array members,
so you might want to let the macro name and/or description reflect that.
Incidentally, there's an autoconf macro to detect whether a C compiler
supports them:
-- Macro: AC_C_FLEXIBLE_ARRAY_MEMBER
If the C compiler supports flexible array members, define
`FLEXIBLE_ARRAY_MEMBER' to nothing; otherwise define it to 1.
That way, a declaration like this:
struct s
{
size_t n_vals;
double val[FLEXIBLE_ARRAY_MEMBER];
};
...
+ */
+#define VIR_ALLOC_VAR(ptr, type, count) virAlloc(&(ptr), sizeof(*(ptr)) +
(sizeof(type) * count))
+
+/**
* VIR_REALLOC_N:
* @ptr: pointer to hold address of allocated memory
* @count: number of elements to allocate
This new allocator should detect overflow, similarly to how
virReallocN does, in case the product would overflow size_t:
int virReallocN(void *ptrptr, size_t size, size_t count)
{
...
if (xalloc_oversized(count, size)) {
errno = ENOMEM;
return -1;
}
Finally, if you manage to leave it as a macro,
you'll want to parenthesize "count" on the RHS.
Otherwise, passing e.g., "n + 1" as the count will allocate
too little space for any type with size larger than 1.