我有这个功能
char* Readfiletobuffer(char* file, FILE* fp){
char * buffer;
int file_size;
fp = fopen(file, "r");
if (fp != NULL) {
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
buffer = (char*) malloc((file_size + 1) * sizeof(char));
fseek(fp, 0, SEEK_SET);
fread(buffer, file_size, 1, fp);
buffer[file_size] = '\0';
return buffer;
} else {
printf("error loading file");
}
fclose(fp);
}
我在程序中调用1050次,并在第1019次
fopen()
返回一个NULL
指针。它不依赖于文件,始终是第1019次,因此我认为这是释放内存的原因,但是为什么
fclose()
调用不够?有人有主意吗?
最佳答案
您的程序可以使用全局变量errno
告诉您,许多函数在失败时会将错误代码分配给该变量。与strerror
结合使用以提供易于理解的错误消息,您可以将错误处理更改为类似这样的内容。
#include <errno.h>
#include <string.h>
...
fp = fopen(file, "r");
if (fp == NULL) {
fprintf(stderr, "Could not open '%s': %s", file, strerror(errno));
exit(1);
}
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
...
注意,使用early exit可以避免将整个函数嵌套在if / else块中。
另请注意,您无法检查其余文件操作。
fseek
,ftell
和fread
都可能失败。您都需要类似的检查。建议您编写一些包装程序,而不是在错误处理时乱扔代码,而可能会忘记在几个地方这样做。FILE *open_file(const char *filename, const char *mode) {
FILE *fp = fopen(filename, mode);
if( fp == NULL ) {
fprintf(
stderr, "Could not open '%s' for '%s': %s\n",
filename, mode, strerror(errno)
);
exit(1);
}
return fp;
}
请注意,这不是最佳的错误处理方式,它只是在错误时退出。在学习C的这一阶段,最好是对错误进行纾困。如果您执行了
return NULL
赔率之类的操作,那么您将没有错误处理来处理空指针,它只会反弹,从而引起神秘的问题,并在稍后的代码中崩溃。现在最好停止并着火,使其尽可能接近错误。剧透警报:您的进程没有文件句柄,因为您没有关闭文件。与@BLUEPIXY correctly points out in the comments一样,
fclose
是正常返回之后的结果,只有在文件打开失败时才会发生。由于您要传递文件指针,也许您打算以后使用它?在这种情况下,您不能保留那么多打开的文件,而必须重新设计代码。如果不是,则因为函数正在打开它,所以没有理由将其传递。
如果使用
-Wall
打开了警告,则应该已经收到了这样的警告。test.c:23:1: warning: control may reach end of non-void function [-Wreturn-type]
}
如果该文件无法打开,则不会返回任何内容,那不是很好。
不要忽略您的警告,请修复所有警告。调查此警告可能会指出问题所在。
检查所有文件操作,以确保它们成功。
在错误消息中包含
strerror(errno)
,以便您了解失败原因。调查并修复所有警告。