[英]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.