我有这个功能

 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块中。

另请注意,您无法检查其余文件操作。 fseekftellfread都可能失败。您都需要类似的检查。建议您编写一些包装程序,而不是在错误处理时乱扔代码,而可能会忘记在几个地方这样做。

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),以便您了解失败原因。
调查并修复所有警告。

10-07 19:52
查看更多