【发布时间】:2020-09-14 09:57:45
【问题描述】:
在处理返回指向 C 字符串的 malloc 指针的函数时,最佳实践是什么?
这是一个例子:
FILE *f;
char *tmp;
for (i = 0; i <= 10; i++) {
tmp = concat(fn, i);
f = fopen(tmp, "w");
free(tmp);
// read f, do something useful ...
fclose(f);
}
char* concat(char *a, int b) 返回一个指向新 C 字符串的指针,其中包含 a 和 b 的串联。
我不仅必须指定一个临时指针,然后将其传递给fopen,我还必须每次都传递给free(tmp)。我宁愿喜欢这样的东西:
FILE *f;
char *tmp;
for (i = 0; i <= 10; i++) {
f = fopen(concat(fn, i), "w");
// read f, do something useful ...
fclose(f);
}
但这当然会导致内存泄漏。那么这里的最佳实践是什么?像concat(char *a, int b, char *result) 这样的结果应该是生成的 C 字符串的预分配内存?此解决方案有其缺点,例如 result 的大小有限或不是最佳大小。
【问题讨论】:
-
当一个函数返回一个
malloced 指针时,调用者必须负责freeing它。 -
@lurker
concat可以返回一个NULL,fopen不能使用NULL作为第一个参数,而且free无法使用concat的结果接近。 -
@Youssef13: That is not true. 这是教给学生的常规练习,但既不是 C 标准的强制要求,也不是在所有情况下有益的。在为通用多用户系统编写程序时,如果您要分配内存并在整个程序执行期间保留它,那么最后释放它是没有意义的,这样做可能会对性能。
-
@EricPostpischil 你应该总是
free的主要原因是这样做会暴露程序中其他地方的堆损坏错误。因为在调用free时会发生崩溃,这使您能够及早发现该错误。链接答案中描述的问题实际上与堆分配无关,而是与某个操作系统如何处理交换文件以及如何设计该特定操作系统的 malloc 和堆 API 的库端口有关。 -
@EricPostpischil 如果您担心这一点,您可以随时从发布版本中忽略
free。一般来说,我怀疑程序在退出时冻结的主要原因是它们从主 GUI 线程进行清理。而不是尽快关闭 GUI,让一些后台线程在后台清理工作,将计算机的控制权交还给用户。这是计算机游戏中的一个主要问题,例如,即使已加载到 RAM 而不是交换文件中,退出时也会冻结。