提问人:IPribec 提问时间:1/30/2023 最后编辑:Vlad from MoscowIPribec 更新时间:1/30/2023 访问量:120
C 语言中释放函数的典型原型是什么?
What is the typical prototype for a deallocation function in C?
问:
查看 StackOverflow 上示例上的代码,我注意到对象释放有两个不同的原型:
struct foo *foo_create(int);
void foo_free_v1(struct foo *);
void foo_free_v2(struct foo **);
void bar() {
struct *foo = foo_create(7);
// ...
// Version 1
foo_free_v1(foo);
// Version 2
foo_free_v2(&foo);
}
标准库函数使用第一种形式。free
第二种形式是 C 中的惯用语吗?如果是,出于什么目的?
答:
那些采用指针到指针的那些这样做是因为它们具有额外的便利性,可以自动为您清空您的变量。
它们可能如下所示:
void foo_free_v1(struct foo *f) {
if (f == NULL) return; // This has been freed before, don't do it again!
free(f->a);
free(f->b);
free(f->c);
free(f);
}
void foo_free_v2(struct foo **f) {
if (*f == NULL) return; // This has been freed before, don't do it again!
free((*f)->a);
free((*f)->b);
free((*f)->c);
free(*f);
*f = NULL; // Null out the variable so it can't be freed again.
}
这试图防止双重释放错误。这是多么好的想法,值得商榷。请参阅下面的评论线程。
评论
struct foos
size_t foo_count
free
free
free
free
free
在第一个函数中
void foo_free_v1(struct foo *);
用作参数表达式的原始指针将按值传递给函数。这意味着该函数处理传递给该函数的指针值的副本。
更改副本不会影响用作参数表达式的原始指针。
例如,考虑函数定义
void foo_free_v1(struct foo *p)
{
free( p );
p = NULL;
}
函数中的此语句
p = NULL;
不会将原始指针更改为 。它设置为函数局部变量。因此,在调用函数后用作参数表达式的指针将具有无效值。该值不指向现有对象。NULL
NULL
p
在这样声明的第二个函数中
void foo_free_v2(struct foo **);
用作参数表达式的原始指针通过指向它的指针被引用接受。因此,取消引用指针后,您可以直接访问用作参数表达式的原始指针。
考虑一个可能的函数定义
void foo_free_v2(struct foo **p)
{
free( *p );
*p = NULL;
}
在这种情况下,在语句中
*p = NULL;
它是设置为 的原始指针。因此,原始指针没有无效值。NULL
例如,考虑一个唱歌的链表,如
struct SinglyLinkedList
{
int data;
SinglyLinkedList *next;
};
在 main 中,您可以声明列表,例如
struct SinglyLinkedList *head = NULL;
然后,您可以将新节点添加到列表中。初始化指针时,添加新节点的函数将正常工作。head
之后,您可以销毁列表。
如果要调用声明如下的第一个函数
void foo_free_v1(struct SinglyLinkedList *head );
然后,在调用函数后,在 main 中声明的指针将具有无效值。也就是说,会有不一致的地方。该列表没有 already 元素,但其指向 head ode 的指针不等于 。head
NULL
是你调用声明的函数 lik
void foo_free_v1(struct SinglyLinkedList **head );
那么实际上,指向 main 中头节点的指针将等于 NULL,这确实意味着列表是空的。如果您有一个检查列表是否为空的函数,则可以将指针传递给该函数,而不会产生未定义的行为。
C 语言中释放函数的典型原型是什么?
传递指针。如果非 - ,则不返回任何内容或很少使用任何内容。void
void foo_free_v1(foo_type *);
第二种形式()是C语言中的惯用语吗?
foo_free_v2(&foo);
不。
经典示例:foo_free(foo_type *)
foo *f = malloc(sizeof *f);
...
free(f);
FILE *istream = fopen(...);
int count = fscanf(istream, ...);
long offset = ftell(istream, ...);
fclose(istream);
何时使用 foo_free_v2(&foo);
?
Use when 不是指针类型。foo_free_v2(&foo)
foo
例:
typedef struct {
int object1;
int *object2;
int *object3;
...
} foo_type;
foo_type foo = { 0 };
foo_get_resources(&foo, ...);
foo_do_this(&foo, ...);
foo_do_that(&foo, ...);
foo_free(&foo);
评论
foo_free_v2
struct foo