简体   繁体   English

宏的组合行为异常

[英]Combination of macros behaving unusually

Following the advice of Reese's Understanding and Using C Pointers , I defined a 'safe free' combination of function and macro, as follows: 遵循Reese 理解和使用C指针的建议 ,我定义了函数和宏的“安全免费”组合,如下所示:

#define safeFree(p) saferFree((void*)&(p))

void saferFree(void **pp) {
    if (pp !=NULL && *pp !=NULL) {
        free(*pp);
        *pp = NULL;
    }
}

Then, following the advice of Klawonn's 21st Century C , I also defined the 'apply to list' macro as follows: 然后,按照Klawonn的21世纪C的建议,我还定义了“应用于列表”宏,如下所示:

#define Fn_apply(type, fn, ...) {    \
    void *stopper_for_apply = (int[]){0};    \
    type **list_for_apply = (type*[]){__VA_ARGS__, stopper_for_apply};    \
    for (int i = 0; list_for_apply[i] != stopper_for_apply; i++) {    \
        fn(list_for_apply[i]);    \
    }    \

These are both defined in one file. 这些都在一个文件中定义。 Then, in another file (which includes these), I have a struct, which contains an internal array which is dynamically allocated. 然后,在另一个文件(包括这些文件)中,我有一个结构,其中包含一个动态分配的内部数组。 Now, I've defined a custom deallocation function for this struct, which looks roughly like this: 现在,我为该结构定义了一个自定义释放函数,该函数大致如下所示:

void deallocate (S** s_ptr) {
    safeFree((*s_ptr)->arr); //deallocates the array
    safeFree(*s_ptr); //deallocates the struct
}

Now, I've tested it with the following code: 现在,我已经使用以下代码对其进行了测试:

S* foo = allocate(); //allocates a new struct, makes the internal array as well
deallocate(&foo);
assert(!foo);

With the above deallocate , this passes. 通过上面的deallocate ,这通过了。 However, if I change deallocate to this: 但是,如果我将deallocate更改为此:

void deallocate (S** s_ptr) {
    Fn_apply(void, safeFree, (*s_ptr)->arr, *s_ptr);
}

The memory gets removed fine, but the assertion above fails. 内存可以很好地删除,但是上面的断言失败。 Did I miss something? 我错过了什么?

I created this compilable code from your question: 我根据您的问题创建了此可编译代码:

#include <assert.h>
#include <stdlib.h>

typedef struct S
{
    int *arr;
} S;

#define safeFree(p) saferFree((void *) & (p))

extern S *allocate(void);
extern void saferFree(void **p);
extern void deallocate(S **s_ptr);
extern void deallocate2(S **s_ptr);
extern void function(void);

void saferFree(void **pp)
{
    if (pp != NULL && *pp != NULL)
    {
        free(*pp);
        *pp = NULL;
    }
}

#define Fn_apply(type, fn, ...) {    \
        void *stopper_for_apply = (int[]){0};    \
        type **list_for_apply = (type *[]){__VA_ARGS__, stopper_for_apply};    \
        for (int i = 0; list_for_apply[i] != stopper_for_apply; i++) {    \
            fn(list_for_apply[i]);    \
        } }

void deallocate(S **s_ptr)
{
    safeFree((*s_ptr)->arr); // deallocates the array
    safeFree(*s_ptr); // deallocates the struct
}

void function(void)
{
    S *foo = allocate(); // allocates a new struct, makes the internal array as well
    deallocate(&foo);
    assert(!foo);
}

void deallocate2(S **s_ptr)
{
    Fn_apply(void, safeFree, (*s_ptr)->arr, *s_ptr);
}

I ran the preprocessor on it, and then formatted the section from the structure definition onwards. 我在其上运行预处理器,然后从结构定义开始格式化该节。 That gives: 这给出了:

typedef struct S
{
    int *arr;
} S;


extern S *allocate(void);
extern void saferFree(void **p);
extern void deallocate(S **s_ptr);
extern void deallocate2(S **s_ptr);
extern void function(void);

void saferFree(void **pp)
{
    if (pp != ((void *)0) && *pp != ((void *)0))
    {
        free(*pp);
        *pp = ((void *)0);
    }
}

# 33 "fz.c"
void deallocate(S **s_ptr)
{
    saferFree((void *) &((*s_ptr)->arr));
    saferFree((void *) &(*s_ptr));
}

void function(void)
{
    S *foo = allocate();
    deallocate(&foo);
    (__builtin_expect(!(!foo), 0) ? __assert_rtn(__func__, "fz.c", 43, "!foo") : (void)0);
}

void deallocate2(S **s_ptr)
{
    {
        void *stopper_for_apply = (int[]){0};
        void **list_for_apply = (void *[]){
            (*s_ptr)->arr, *s_ptr, stopper_for_apply
        };
        for (int i = 0; list_for_apply[i] != stopper_for_apply; i++)
        {
            saferFree((void *) &(list_for_apply[i]));
        }
    }
}

This code confused Uncrustify 0.60 into producing uncompilable code; 该代码将Uncrustify 0.60混淆为无法生成的代码。 it botched the formatting of the two array literals, losing the trailing semicolons. 它破坏了两个数组文字的格式,丢失了尾随的分号。

I think the output shows the problem. 我认为输出显示了问题。 You're working with copies of the (*s_ptr)->arr and *s_ptr in the list_for_apply array, rather than the originals. 您正在使用list_for_apply数组中的(*s_ptr)->arr*s_ptr list_for_apply ,而不是原始list_for_apply So, the two lots of code simply make different assumptions about what's going on, and therefore come to the wrong conclusion. 因此,这两段代码只是对所发生的事情做出了不同的假设,因此得出了错误的结论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM