我经常想使用一个假设的 free_if_heap(void *ptr)
函数,因为这可以让我不关心地返回 malloc、静态或堆栈对象。例如
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)
和一百个其他变体。
最佳答案
函数void free_if_heap(void *ptr)
无法可移植地实现*,但在选定的目标上可能是可能的,具体取决于malloc()
的本地实现。
如果您不能或不想处理分配对象的生命周期,您应该使用不同的编程语言和垃圾收集器。 C 有许多有效的替代品,例如 Go。您还可以尝试使用 C 的保守垃圾收集器,例如 Boehm–Demers–Weiser garbage collector .
但请注意,跟踪内存分配的对象并在使用后正确处置它们并不那么困难,但需要一致的约定:例如,您的 foo 函数应始终返回分配的字符串或空指针:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *foo(int arg) {
if (arg < 0) {
return strdup("arg is negative");
}
if (arg > 0) {
size_t size = snprintf(NULL, 0, "%i is an invalid value", arg);
char *ret = malloc(size + 1);
if (ret != NULL) {
snprintf(ret, size + 1, "%i is an invalid value", arg);
return ret;
}
}
return NULL;
}
int main(void) {
for (int i = -1; i < 2; ++i) {
char *err = foo(i);
if (err) {
printf("Error: %s\n", err);
free(err);
}
}
return 0;
}
(*) 可移植的实现将是微不足道且无效的:void free_if_heap(void *ptr) {}
关于c - 反对 free_if_heap(void *ptr)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63408530/