1

I want to write macro in c code to freeing many pointers like this :

FREE(ptr1, ptr2, ptr3, ptr4, ptrx);

For me, this is better than

 FREE(ptr1); 
 FREE(ptr2);
 FREE(ptr3);
 FREE(ptr4);
 FREE(ptrx);

Thanks in advance

Regards,

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
Anis_Stack
  • 3,306
  • 4
  • 30
  • 53
  • 6
    This is not better. It is absolutely stupid. -1. It will only confuse every new developer and won't really help anything. – Jan Hudec Jan 08 '14 at 09:14
  • 1
    I believe this is possible with variadic macros, but writing a variadic macro for this is rather overkill. Make sure you're not using a jillion variables where an array or other comparable data structure would be more reasonable. – user2357112 Jan 08 '14 at 09:17
  • are you sure that can't help to reduce the number of line of c code !!! – Anis_Stack Jan 08 '14 at 09:18
  • 3
    @JanHudec why this is a stupid idea. the OP can ask what he wants according to his needs and personally I see it's a good idea to free all pointers in only one call – MOHAMED Jan 08 '14 at 09:18
  • 3
    You should instead maybe reconsider why you have so many pointers, e.g. using an array of pointers would make it more readable. `for (int i = 0; i < MAX_POINTERS; ++i) free( ptr[i] );` – AndersK Jan 08 '14 at 09:25
  • 2
    Even if it is a bad idea, it is a valid question and I don't see the reason for -1 or even -3. – glglgl Jan 08 '14 at 09:48

5 Answers5

5

Use a function with variable number of function arguments. Header: stdarg.h.

I had a little fun with the solution.

#define FREE( ... ) Free( &free_stop , __VA_ARGS__ , &free_stop )
//takes any number of pointer arguments,(at least one )( can also take NULL which is handled by free )

int free_stop ;

void Free( void* point , ... )  
{
    if( !point )
        return ;

    va_list list ;
    va_start( list , point ) ;

    void* p = va_arg( list , void* ) ;
    while( p != point ) 
    {
        free( p ) ;
        p = va_arg( list , void* ) ;
    }


    va_end( list ) ;

}

Usage:

FREE( ptr1 , ptr2 , ptr3 ) ;   //don't have to NULL terminate
this
  • 5,229
  • 1
  • 22
  • 51
  • I want to avoid include new header file "stdarg.h" for that reason I choose user3162146's solution ; thanks – Anis_Stack Jan 08 '14 at 11:29
  • @self Is it possible to use the address of the Free function instead of the `int free_stop` address like this: `Free( &Free , __VA_ARGS__ , &Free )` – MOHAMED Jan 08 '14 at 11:33
4

You can pass variable number of arguments in macro. Following code works fine:

#define FREE_ALL(...) \
do { \
    int i=0;\
    void *pta[] = {__VA_ARGS__}; \
    for(i=0; i < sizeof(pta)/sizeof(void*); i++) \
    { \
        free(pta[i]); \
    }\
} while(0)
Anis_Stack
  • 3,306
  • 4
  • 30
  • 53
Cool Goose
  • 870
  • 10
  • 16
  • All multiline macros should be enclosed with a do{}while statement. Also using __VA_ARGS__ for anything other than a function parameter is not specified by C standard and the result might vary by different compilers. – this Jan 08 '14 at 10:33
1

Maybe you can define a function like:

void freeargs(void *ptr1, ...) {
    // code for freeing variable number of arguments until NULL pointer.
}

and then the macro:

#define FREE(...) freeargs(__VA_ARGS__, NULL)
Marian
  • 7,402
  • 2
  • 22
  • 34
  • 1
    your solution looks good But it will not work correctly if one of the input pointers is NULL – MOHAMED Jan 08 '14 at 09:47
  • And if one of the pointers was already `NULL`, this fails. Maybe it would be useful to have a special value (such as the address of a static variable or such) as a stopping sentinel. – glglgl Jan 08 '14 at 09:47
  • If you had a NULL pointer among the arguments your original program would crash. – Marian Jan 08 '14 at 09:49
  • 1
    @MarianV the free of NULL does not cause a crash http://stackoverflow.com/questions/13471749/free-a-null-pointer – MOHAMED Jan 08 '14 at 09:50
  • @MarianV may be you have to use another specific stop address like 0xFFFFFFFF but you have to see first if it could be a valid stop address – MOHAMED Jan 08 '14 at 09:53
  • Yes. It may be safer to use (for example) the address of freeargs as the last argument `#define FREE(...) freeargs(__VA_ARGS__, freeargs)` or something like @MOHAMED proposes – Marian Jan 08 '14 at 09:55
  • @MOHAMED You can always declare a const global variable and use its address. – this Jan 08 '14 at 10:12
  • @self I know but the question here what is the safe address to use. I suggested 0xFFFFFFFF but I do not know if it's a valid address – MOHAMED Jan 08 '14 at 10:14
  • @MOHAMED ... An address of a global var declared for this purpose is safe to use. – this Jan 08 '14 at 10:14
  • @self `freeargs` is the address of the function itself. – Marian Jan 08 '14 at 11:53
0

I think it's a neutral idea. positive:If you want to free pointers together,it can help.but it seemly doesn't save much things. negative:if the pointers may free dispersedly,then you should wait them used,which may cause pointers fogetten. by the way,the macos can be

#define FREE(ptr1, ptr2, ptr3, ptr4, ptrx) (free(ptr1);free(ptr2);free(ptr3);free(ptr4);free(ptr5);)
Nibnat
  • 119
  • 7
0

use BOOST

#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/tuple/to_seq.hpp>

#define PROC(r, f, elem) f(elem);
#define FREE(...) BOOST_PP_SEQ_FOR_EACH(PROC, free, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__)))
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70