根据Reese的理解和使用C指针的建议,我定义了函数和宏的'安全免费'组合,如下所示:
#define safeFree(p) saferFree((void*)&(p))
void saferFree(void **pp) {
if (pp !=NULL && *pp !=NULL) {
free(*pp);
*pp = NULL;
}
}
然后,按照Klawonn的 21st Century C 的建议,我还将'apply to list'宏定义如下:
#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]); \
} \
这些都在一个文件中定义。然后,在另一个文件(包括这些)中,我有一个struct,它包含一个动态分配的内部数组。现在,我为这个结构定义了一个自定义的释放函数,它看起来大致如下:
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);
}
内存被删除很好,但上面的断言失败了。我错过了什么吗?
答案 0 :(得分:1)
我从你的问题中创建了这个可编译的代码:
#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混淆为生成无法编译的代码;它破坏了两个数组文字的格式,丢失了尾随的分号。
我认为输出显示了问题。您正在处理(*s_ptr)->arr
数组中的*s_ptr
和list_for_apply
的副本,而不是原件。因此,这两个代码只是对正在发生的事情作出不同的假设,因此得出了错误的结论。