FILE*open\u FILE\u编号(const char*str,int number)
{
尺寸=strlen(str)+32;
char*path=malloc(大小);
if(路径==NULL)
{
返回NULL;
}
snprintf(路径、大小、“%s%d”、str、编号);
FILE*FILE=fopen(路径“w”);
自由(路径);
返回文件;
}
对于(i=0;i
处理将malloc'd指针返回C字符串的函数时,最佳做法是什么
最佳实践:不要使用它们。一个期望调用者释放返回数据的库几乎肯定设计得很糟糕,只有极少数例外。我们从40年的C语言历史中了解到这一点,在C语言历史中,糟糕的编写库已经造成了数以百万计的内存泄漏错误
合理、有用的库API设计的基本规则是:
分配东西的人负责清理自己的烂摊子。
因为C没有RAII或构造函数/析构函数,不幸的是,SAN文库需要为清理提供一个函数,并且您需要记住调用它。如果它不提供这样的函数,您可能需要考虑编写这样的包装函数来纠正它们的坏的库设计。>
如果您是实现库的人,则应始终尽可能将内存分配留给调用方。这通常是由函数获取指向其写入的缓冲区的指针来完成的。然后将其留给调用方以分配足够的内存(如 strcpy/strcat),或者提供一个具有最大缓冲区大小的变量,然后函数返回实际使用的缓冲区大小(如fgets)
在您的示例中,设计合理的concat可能如下
const char* concat (char* restrict dst, const char* restrict src, int i);
其中,src是源字符串,i是要添加的整数,dst是调用者提供的足够大的缓冲区。为了方便起见,该函数还可以返回一个相当于dst的指针。上述函数还实现了适当的常量正确性,并使用restrict进行了微优化传递的指针不允许重叠
用法:
char buf [LARGE_ENOUGH];
fp = fopen(concat(buf, foo, i), "w");
当一个函数返回一个malloced指针时,调用方必须负责freeing它。@潜伏者concat可以返回一个NULL,fopen不能使用NULL作为第一个参数,而且使用这种方法无法释放concat的结果@Youssef13:这是一种向学生传授的常规做法,但既不是C标准的强制要求,也不是在所有情况下都有好处。在为通用多用户系统编写程序时,如果要分配内存并在整个程序执行过程中保留内存,那么在最后释放内存是没有意义的,这样做可能会产生adverse对性能的影响。@EricPostpischil您应该总是free的主要原因是这样做会暴露出程序中其他地方的堆损坏错误。因为调用free会导致崩溃,这使您能够及早发现该错误。链接答案中描述的问题与o堆分配,但特定操作系统如何处理交换文件,以及特定操作系统的malloc库端口和堆API是如何设计的。@EricPostpischil您始终可以省去空闲const char* concat (char* restrict dst, const char* restrict src, int i);
char buf [LARGE_ENOUGH];
fp = fopen(concat(buf, foo, i), "w");
|