[libvirt] [PATCH 1/3] Added VIR_ALLOC_VAR macro

Jim Meyering jim at meyering.net
Tue Feb 16 09:14:34 UTC 2010


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.




More information about the libvir-list mailing list