簡體   English   中英

宏的組合行為異常

[英]Combination of macros behaving unusually

遵循Reese 理解和使用C指針的建議 ,我定義了函數和宏的“安全免費”組合,如下所示:

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

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

然后,按照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]);    \
    }    \

這些都在一個文件中定義。 然后,在另一個文件(包括這些文件)中,我有一個結構,其中包含一個動態分配的內部數組。 現在,我為該結構定義了一個自定義釋放函數,該函數大致如下所示:

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

現在,我已經使用以下代碼對其進行了測試:

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

通過上面的deallocate ,這通過了。 但是,如果我將deallocate更改為此:

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

內存可以很好地刪除,但是上面的斷言失敗。 我錯過了什么?

我根據您的問題創建了此可編譯代碼:

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

我在其上運行預處理器,然后從結構定義開始格式化該節。 這給出了:

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]));
        }
    }
}

該代碼將Uncrustify 0.60混淆為無法生成的代碼。 它破壞了兩個數組文字的格式,丟失了尾隨的分號。

我認為輸出顯示了問題。 您正在使用list_for_apply數組中的(*s_ptr)->arr*s_ptr list_for_apply ,而不是原始list_for_apply 因此,這兩段代碼只是對所發生的事情做出了不同的假設,因此得出了錯誤的結論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM