Using void *, void ** and the variational function

I want to write a function that frees as many pointers as needed. So, I have this:

void    myfree(size_t n, ...)
{
    void    **del;
    va_list ap;

    va_start(ap, n);
    while (n > 0)
    {
        del = va_arg(ap, void **);
        free(*del);
        *del = NULL;
        --n;
    }
    va_end(ap);
}

I call it the following:

char *one = malloc(x);
sometype_t *two = malloc(x);
myfree(2, &one, &two);

I guess one, and twonow point to NULL. It seems to work, but I'm still a little worried. I did some research about void**, but I'm not sure if my function really is (UB are you there?)


During my research and tests, I tried some things that I really do not understand.

Say we have this function

void    f(void **ptr)
{
} 

If i call it so

int *intptr = NULL;
f(&intptr);

I get a compiler warning: warning: incompatible pointer types passing 'int **' to parameter of type 'void **'

So i tried this

int *intptr = NULL;
f( & ((void *)intptr) );

Compiler Error: error: cannot take the address of an rvalue of type 'void *'

But if I do

void *voidptr = NULL;
f(&voidptr); // I can take the address of a void pointer right ?

void*, void** / . myfree(), . - , :)

+4
3

C void * void *, void **. , , , , . , undefined.

, , :

#define myfree(ptr) do { free(ptr); ptr = NULL; } while (0)
+1

@dbush , UB. , , . NULL .

void myfree(size_t n, ...)
{
    void* del;
    va_list ap;

    va_start(ap, n);
    while (n > 0)
    {
        del = va_arg(ap, void *);
        free(del);
        --n;
    }
    va_end(ap);
}
char *one = malloc(x);
sometype_t *two = malloc(x);
myfree(2, one, two);
+1

, , , undefined (UB).


myfree(2, &one, &two); void * void **. &one, &two char **, sometype_t **.

myfree() , void **:

void ** del = va_arg(ap, void **);`

:

va_arg .... ... ..., undefined C11dr §7.16.1.1 2

, void ** char **, sometype_t **. , , . , UB.


OP, , :

: : , 'int **' type 'void **'

f(&intptr);. §7.16.1.1 2 . :

. , undefined. C11dr §6.3.2.3 7

, , . , UB , .


Alternative

void *. , free'd NULL.

void myfree(size_t n, ...) {
  void *del;  // one *
  va_list ap;

  va_start(ap, n);
  while (n > 0) {
     del = va_arg(ap, void *);
     free(del);
     --n;
    }
  va_end(ap);
}

void* . . printf("%p\n", (void*) two);

char *one = malloc(x);
sometype_t *two = malloc(x);
void *three = malloc(x);
myfree(3, one, (void*) two, three);

2

, , .

Maybe, instead myfree(n, ...), what about encoding some more popular sizes, even as a macro, and leave that out? This, of course, meets most coding needs and, of course, avoids the error myfree(3, p1, p2). Recall that it is normal to callfree4(p1, p2,p3,0);

free2(void *p1, void *p2)`
free3(void *p1, void *p2, void *p3)
free4(void *p1, void *p2, void *p3, void *p4)
// maybe a few others
+1
source

Source: https://habr.com/ru/post/1693732/


All Articles