Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22475

Allocating through a pointer to a pointer parameter

$
0
0

I have this macro:


/*
 * int  callocs(type **ptr, size_t nmemb);
 *
 * Safe & simple wrapper for `calloc()`.
 *
 * PARAMETERS:
 * ptr:     Memory will be allocated, and a pointer to it will be stored
 *          in *ptr.
 * nmemb:   Number of elements in the array.
 *
 * RETURN:
 *  0:          OK.
 *  != 0:       Failed.
 *
 * FEATURES:
 * - Safely computes the element size (second argument to `calloc()`).
 * - Returns non-zero on error.
 * - Doesn't cast.
 * - The pointer stored in `*ptr` is always a valid pointer or NULL.
 *
 * EXAMPLE:
 *      #define ALX_NO_PREFIX
 *      #include <libalx/base/stdlib/alloc/callocs.h>
 *
 *              int *arr;
 *
 *              if (callocs(&arr, 7))       // int arr[7];
 *                      goto err;
 *
 *              // `arr` has been succesfully allocated here
 *              free(arr);
 *      err:
 *              // No memory leaks
 */
#define callocs(ptr, nmemb) (                                           \
{                                                                       \
        __auto_type     ptr_    = (ptr);                                \
                                                                        \
        *ptr_   = calloc(nmemb, sizeof(**ptr_));                        \
                                                                        \
        !(*ptr_);                                                       \
}                                                                       \
)

and I would like it to be a function to improve safety. This would be the first idea:

#define callocs(ptr, nmemb) (                                           \
{                                                                       \
        __auto_type     ptr_    = (ptr);                                \
                                                                        \
        callocs__(ptr_, nmemb, sizeof(**ptr_));                         \
}                                                                       \
)


int     callocs__(void **ptr, ptrdiff_t nmemb, size_t size)
{

        if (nmemb < 0)
                goto ovf;

        *ptr    = calloc(nmemb, size);

        return  !*ptr;
ovf:
        errno   = ENOMEM;
        *ptr    = NULL;
        return  ENOMEM;
}

But then the compiler complains with:

error: passing argument 1 of callocs__ from incompatible pointer type [-Werror=incompatible-pointer-types]
note: in expansion of macro callocs
note: expected void ** but argument is of type struct My_Struct **

Is a simple explicit cast to (void **) safe?:

#define callocs(ptr, nmemb) (                                           \
{                                                                       \
        __auto_type     ptr_    = (ptr);                                \
                                                                        \
        callocs__((void **)ptr_, nmemb, sizeof(**ptr_));                \
}                                                                       \
)

By safe I mean both from the Standard point of view (which I guess is not) and from implementations point of view (in this specific case, GNU C) (which I'm not sure).

And if not, would an intermediate pointer of type void * be enough?:

#define callocs(ptr, nmemb) (                                           \
{                                                                       \
        __auto_type     ptr_    = (ptr);                                \
        void            *vp_;                                           \
        int             ret_;                                           \
                                                                        \
        ret_    = callocs__(&vp_, nmemb, sizeof(**ptr_))                \
        *ptr_   = vp_;                                                  \
        ret_;                                                           \
}                                                                       \
)

Is there any other solution?


Viewing all articles
Browse latest Browse all 22475

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>