【问题标题】:how to freeing pointers using macro in c如何在c中使用宏释放指针
【发布时间】:2014-01-08 09:12:23
【问题描述】:

我想用 c 代码编写宏来释放许多这样的指针:

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

对我来说,这比

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

提前致谢

问候,

【问题讨论】:

  • 这不是更好。这绝对是愚蠢的。 -1。它只会让每个新开发人员感到困惑,并且不会真正帮助任何事情。
  • 我相信这可以通过可变参数宏实现,但是为此编写可变参数宏是相当大的。确保您没有使用数组或其他可比较的数据结构更合理的数个变量。
  • @JanHudec 为什么这是一个愚蠢的想法。 OP 可以根据他的需要询问他想要什么,我个人认为在一次调用中释放所有指针是个好主意
  • 你应该重新考虑为什么你有这么多指针,例如使用指针数组将使其更具可读性。 for (int i = 0; i < MAX_POINTERS; ++i) free( ptr[i] );
  • 即使这是一个坏主意,它也是一个有效的问题,我看不出 -1 甚至 -3 的原因。

标签: c free


【解决方案1】:

使用具有可变数量的函数参数的函数。标头:stdarg.h.

这个解决方案让我很开心。

#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 ) ;

}

用法:

FREE( ptr1 , ptr2 , ptr3 ) ;   //don't have to NULL terminate

【讨论】:

  • 我想避免包含新的头文件“stdarg.h”,因此我选择了user3162146的解决方案;谢谢
  • @self 是否可以像这样使用Free函数的地址代替int free_stop地址:Free( &Free , __VA_ARGS__ , &Free )
【解决方案2】:

您可以在宏中传递可变数量的参数。以下代码工作正常:

#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)

【讨论】:

  • 所有多行宏都应该用 do{}while 语句括起来。此外,C 标准未指定将 VA_ARGS 用于函数参数以外的任何内容,并且结果可能因不同的编译器而异。
【解决方案3】:

也许您可以定义如下函数:

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

然后是宏:

#define FREE(...) freeargs(__VA_ARGS__, NULL)

【讨论】:

  • 您的解决方案看起来不错但是如果输入指针之一为 NULL,它将无法正常工作
  • 如果其中一个指针已经是NULL,则失败。也许有一个特殊的值(例如静态变量的地址等)作为停止标记会很有用。
  • 如果你的参数中有一个 NULL 指针,你的原始程序就会崩溃。
  • @MarianV 无 NULL 不会导致崩溃 stackoverflow.com/questions/13471749/free-a-null-pointer
  • @MarianV 可能您必须使用另一个特定的停止地址,例如 0xFFFFFFFF,但您必须先查看它是否是有效的停止地址
【解决方案4】:

我认为这是一个中立的想法。 正:如果你想一起释放指针,它可以提供帮助。但它似乎并没有节省多少东西。 否定:如果指针可能分散释放,那么您应该等待它们使用,这可能会导致指针模糊。 顺便说一下,macos可以是

#define FREE(ptr1, ptr2, ptr3, ptr4, ptrx) (free(ptr1);free(ptr2);free(ptr3);free(ptr4);free(ptr5);)

【讨论】:

    【解决方案5】:

    使用增强

    #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__)))
    

    【讨论】:

    • @self 是的,只需要预处理器。
    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 2011-10-28
    • 2011-07-18
    相关资源
    最近更新 更多