【发布时间】:2020-08-14 07:39:32
【问题描述】:
我经常想使用一个假设的free_if_heap(void *ptr) 函数,因为这可以让我返回 malloc'd、静态或堆栈对象而不用关心。例如
char *foo(int arg) {
if (arg < 0) {
return "arg is negative";
}
if (arg > 0) {
size_t size = snprintf(NULL, 0, "%i is an invalid value", arg);
char *ret = malloc(size + 1); // FIXME: handle failure
sprintf(ret, "%i is an invalid value", arg);
// I use a varargs macro for the three lines above, to avoid format string duplication errors.
}
return NULL;
}
void main(void) {
for (int i = -1; i < 2; ++i) {
char *err = foo(i);
if (err) {
printf("Error: %s\n", err);
free_if_heap(err);
}
}
}
显然,这样的函数肯定不是一个好主意,因为它甚至从未达到 malloc 库的水平,更不用说 C 标准了。
为什么free_if_heap(void *ptr) 是个坏主意?
更新:
函数foo 只是一个函数示例,它可以返回指向malloc 数据或静态/全局数据的指针。这不是一个有目的的严肃功能。
更新:
需要知道指针(其他已知类型,如char *)是否指向堆与需要知道void * 指针指向的数据类型不同。
free_if_heap(void *ptr) 采用void * 参数以避免free_if_heap_char(char *ptr)、free_if_heap_int(int *ptr) 和其他一百个变体。
【问题讨论】:
-
@Yunnosch 返回字符串的
size是使用snprint计算的,不写字符,而只是使用它的返回值。所需的size然后是malloc'd,并且使用具有相同格式字符串的sprintf将错误写入其中。我在宏中执行此操作,因此我只需编写一次格式字符串,避免错误。 -
哦,我明白了。你不是在展示一个实现,你是在展示你想如何使用它。除了给定的例子,请解释更多。
-
老实说,我认为问题是由可能返回需要释放的指针或不需要释放的指针的函数引起的。在我看来,这是一个设计错误。原因见我上面提供的链接。
-
Why is free_if_heap(void *ptr) a bad idea?因为不需要确定指针是否指向堆所需的开销。 C程序员可以自己做。 C 程序员会想自己做,这样就不会执行神奇的附加代码。这个问题不是基于意见吗? -
@Yunnosch 那么这使它成为无法回答的问题之一“为什么 C 中没有某些东西”,不是吗?不是,因为它从未实施过。因为它不存在。