我有一个程序,在这个程序中我使用了很多malloc(和其他类似的函数)来为不同的数据类型分配内存。正如我们所知,这些功能可能会失败。我如何编写一个整洁的代码来检查内存是否成功分配,如果没有,则释放所有以前的malloc(如果有的话)?
我想也许可以写一个函数来释放我malloc的每个指针,如果它们是!=NULL。但是我需要发送很多参数。有更好的主意吗?
谢谢。
这实际上是一个不平凡的C编码习惯用法问题。一个答案是学习C++并使用auto_pointer
。
在C中,我成功地使用了以下习语。
- 在声明时设置指向
NULL
的所有指针 - 只在需要时分配内存
- 如果分配失败,请设置一个错误值,并在所有指针释放的末尾设置
goto
标签 - 如果由于某种原因需要提前释放指针,请再次将其设置为NULL
- 所有正常的执行都必须进行到底,这样所有的东西都会被释放(没有中间的
return
)
它最终看起来是这样的:
int err = 0;
FOO *p = NULL;
BAR *q = NULL;
BAZ *r = NULL;
p = malloc(...);
if (!p) {
err = P_MALLOC_FAILURE;
goto done;
}
....
q = malloc(...);
if (!q) {
err = Q_MALLOC_FAILURE;
goto done;
}
....
// Done with p. Free it early.
free(p);
p = NULL;
....
done:
free(p);
free(q);
return err;
free
的定义确保了如果指针在末尾仍然为NULL,则不会发生任何事情。如果你不喜欢重复的代码,你可以滥用宏:
#define ALLOC_OR_FAIL(P) do {
P = malloc(sizeof *P);
if (!P) {
err = P ## _MALLOC_FAILURE;
goto done;
} } while (0)
好吧,你可以这样设计你的代码,如果出现错误,你的程序流就会回到调用堆栈,所有函数在返回错误条件时都会释放分配的内存。
如果您的代码组织得不好,那么"整齐"释放所有以前的malloc的唯一可移植方法是,在执行malloc时存储一个malloc全局表,每次调用malloc
或free
(或任何其他分配函数)时都要保持最新。
然而,现代操作系统在进程退出时为您释放所有内存,事实上,它们可以比您更快地做到这一点,因为它们可以一次性释放整个进程的内存分配。IMHO一个实际的决定是直接退出而不显式释放,除非你怀疑你的代码将在一个会泄漏内存的系统上运行。
就像pzaenger说的。。。
ptr = calloc/malloc/realloc(parameters);
if(ptr == NULL)
{
printf("Well shucks...");
}
很简单。
我一直在构建一些代码,目前我也有很多7/8的参数,其中大多数是被取消引用的指针,等等
我有几个函数,还有更多的函数,使用这些相同的7/8参数。因此,为了清理它们,我只需要将它们填充到一个结构(c结构)中。这样,我所要做的就是传递一个参数,即struct(或者很可能是一个ptr到struct)。
现在一开始所要做的就是结构的malloc/calloc内存,然后是结构内任何指针的malloc.calloc内存。
然后你来回传递这个结构,做你需要做的任何事情
最后,您遍历该结构并释放其内部的任何内存malloc/caloc。然后释放结构本身的内存(如果使用了该结构的ptr)。