fclose返回值检查

fclose返回值检查,c,file-io,C,File Io,是否需要检查fclose的返回值?如果我们成功地打开了一个文件,那么它无法关闭的可能性有多大 谢谢 问候,, Jay当您将fwrite写入文件时,它可能不会实际写入任何内容,它可能会保留在缓冲区中(文件对象内部)。调用fflush实际上会将其写入磁盘该操作可能会失败,例如,如果磁盘空间不足,或者存在其他一些I/O错误 fclose也会隐式刷新缓冲区,因此它可能会由于相同的原因而失败。手册页指出,它可能会由于close或fflush可能会失败的任何原因而失败 引述: 如果出现以下情况,close(

是否需要检查fclose的返回值?如果我们成功地打开了一个文件,那么它无法关闭的可能性有多大

谢谢

问候,,
Jay

当您将
fwrite
写入文件时,它可能不会实际写入任何内容,它可能会保留在缓冲区中(文件对象内部)。调用
fflush
实际上会将其写入磁盘该操作可能会失败,例如,如果磁盘空间不足,或者存在其他一些I/O错误

fclose
也会隐式刷新缓冲区,因此它可能会由于相同的原因而失败。

手册页指出,它可能会由于close或fflush可能会失败的任何原因而失败

引述:

如果出现以下情况,close()系统调用将失败:

 [EBADF]            fildes is not a valid, active file descriptor.

 [EINTR]            Its execution was interrupted by a signal.

 [EIO]              A previously-uncommitted write(2) encountered an
                    input/output error.

fflush可能会失败,原因是()会失败,基本上是在您无法实际写入/保存文件的情况下。

如果在应用程序的上下文中,如果fclose()失败,您可以想出一些有用的方法,然后测试返回值。如果不能,请不要。

您必须始终检查fclose()的结果。

fclose可能失败的一个原因是,是否仍有任何数据被缓冲,并且隐式fflush失败。我建议始终调用fflush并在那里执行任何错误处理。

我已经多次看到fclose()返回非零

经过仔细检查,发现真正的问题在于书写,而不是fclose

由于正在写入的内容在实际写入之前被缓冲,当调用fclose()时,所有缓冲区都被刷新。所以,在fclose()期间,写入缓冲suff时出现任何问题,比如磁盘已满。正如David Yell所说的,为了编写一个防弹应用程序,你需要考虑fCutele()的返回值。

你可以(并且应该)报告错误,但从某种意义上说,

在调用fclose()之后,流的任何使用都会导致未定义的行为

  • fclose()
    将在返回之前刷新任何未写入的输出(通过
    fflush()
    ),因此在
    fwrite()
    fprintf()
    时不会报告基础
    write()
    产生的错误,但在执行
    fclose()
    时不会报告。因此,
    write()
    fflush()
    可以生成的任何错误都可以由
    fclose()
    生成

  • fclose()。如果NFS服务器崩溃,则
    close()
    将失败,因此
    fclose()
    也将失败。其他网络文件系统可能也是如此

  • 发件人:

    fclose()调用可能会失败,并且应该 同样认真地检查错误 与所有其他文件操作一样。 听起来很迂腐,对吧?错。在一个 前世,我公司的产品 设法销毁客户的数据 通过在以下情况下忽略故障检查: 关闭一个文件。节目开始了 类似于(意译):

    当然,发生的事情是这样的 fclose()尝试时磁盘空间不足 要编写 数据,因此“tempfile”被截断 而且无法使用。自从fclose()事件以来 未检测到故障,程序正在运行 就这么干了,摧毁了 中现有数据的最佳版本 赞成损坏的版本。以及 墨菲会把它拿走的,受害者在里面 这一特殊事件是最严重的 负责客户服务的人员 部门,有权力的人 购买更多我们的产品或更换 它使用竞争对手的产品-- 纳奇,一个已经 因为其他原因和我们不愉快

    把这一切都归咎于 随之而来的是这个单身汉的痛苦 遗漏,但可能值得指出 客户和我的 以前的公司从此消失了 从企业生态学的角度

    检查那些故障代码


    假设您正在生成数据。您从文件中获取了旧数据,然后对数据进行一些处理,生成更多数据,然后将其写入新文件。您要小心不要覆盖旧文件,因为您知道尝试创建新文件可能会失败,并且希望在这种情况下保留旧数据(有些数据总比没有数据好)。在完成所有成功的
    fwrite()
    之后(因为您仔细检查了
    fwrite()
    的返回值),您将
    fclose()
    文件。然后,您可以
    rename()
    您刚刚编写的文件并覆盖旧文件

    如果
    fclose()
    由于写入错误(磁盘已满?)而失败,那么您只是用一些可能是垃圾的内容重写了上一个好文件。哎呀

    因此,如果它很关键,您应该检查
    fclose()
    的返回值

    在代码方面:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        FILE *ifp = fopen("in.dat", "rb");
        FILE *ofp = fopen("out.dat", "wb");
        char buf[BUFSIZ];
        size_t n;
        int success = 1;
    
        if (ifp == NULL) {
            fprintf(stderr, "error opening in.dat\n");
            perror("in.dat");
            return EXIT_FAILURE;
        }
    
        if (ofp == NULL) {
            fclose(ifp);
            fprintf(stderr, "error opening out.dat\n");
            perror("out.dat");
            return EXIT_FAILURE;
        }
    
        while ((n = fread(buf, 1, sizeof buf, ifp)) > 0) {
            size_t nw;
            if ((nw = fwrite(buf, 1, n, ofp)) != n) {
                fprintf(stderr, "error writing, wrote %lu bytes instead of %lu\n",
                                (unsigned long)n,
                                (unsigned long)nw);
                fclose(ifp);
                fclose(ofp);
                return EXIT_FAILURE;
            }
        }
        if (ferror(ifp)) {
            fprintf(stderr, "ferror on ifp\n");
            fclose(ofp);
            fclose(ifp);
            return EXIT_FAILURE;
        }
    
    #ifdef MAYLOSE_DATA
        fclose(ofp);
        fclose(ifp);
        rename("out.dat", "in.dat"); /* Oops, may lose data */
    #else
        if (fclose(ofp) == EOF) {
            perror("out.dat");
            success = 0;
        }
        if (fclose(ifp) == EOF) {
            perror("in.dat");
            success = 0;
        }
        if (success) {
            rename("out.dat", "in.dat"); /* Good */
        }
    #endif
        return EXIT_SUCCESS;
    }
    
    #包括
    #包括
    内部主(空)
    {
    文件*ifp=fopen(“in.dat”、“rb”);
    文件*ofp=fopen(“out.dat”、“wb”);
    char buf[BUFSIZ];
    尺寸;
    int成功=1;
    如果(ifp==NULL){
    fprintf(stderr,“在.dat中打开时出错\n”);
    perror(“in.dat”);
    返回退出失败;
    }
    如果(ofp==NULL){
    fclose(ifp);
    fprintf(stderr,“打开.dat时出错”);
    perror(“out.dat”);
    返回退出失败;
    }
    而((n=fread(buf,1,sizeof buf,ifp))>0){
    西北尺寸;
    如果((nw=fwrite(buf,1,n,ofp))!=n){
    fprintf(stderr,“写入错误,写入了%lu字节而不是%lu\n”,
    (无符号长)n,
    (无符号长)西北);
    fclose(ifp);
    fclose(ofp);
    返回退出失败;
    }
    }
    中频(铁磁(ifp)){
    fprintf(标准,“ifp上的ferror\n”);
    fclose(ofp);
    fclose(ifp);
    返回退出失败;
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        FILE *ifp = fopen("in.dat", "rb");
        FILE *ofp = fopen("out.dat", "wb");
        char buf[BUFSIZ];
        size_t n;
        int success = 1;
    
        if (ifp == NULL) {
            fprintf(stderr, "error opening in.dat\n");
            perror("in.dat");
            return EXIT_FAILURE;
        }
    
        if (ofp == NULL) {
            fclose(ifp);
            fprintf(stderr, "error opening out.dat\n");
            perror("out.dat");
            return EXIT_FAILURE;
        }
    
        while ((n = fread(buf, 1, sizeof buf, ifp)) > 0) {
            size_t nw;
            if ((nw = fwrite(buf, 1, n, ofp)) != n) {
                fprintf(stderr, "error writing, wrote %lu bytes instead of %lu\n",
                                (unsigned long)n,
                                (unsigned long)nw);
                fclose(ifp);
                fclose(ofp);
                return EXIT_FAILURE;
            }
        }
        if (ferror(ifp)) {
            fprintf(stderr, "ferror on ifp\n");
            fclose(ofp);
            fclose(ifp);
            return EXIT_FAILURE;
        }
    
    #ifdef MAYLOSE_DATA
        fclose(ofp);
        fclose(ifp);
        rename("out.dat", "in.dat"); /* Oops, may lose data */
    #else
        if (fclose(ofp) == EOF) {
            perror("out.dat");
            success = 0;
        }
        if (fclose(ifp) == EOF) {
            perror("in.dat");
            success = 0;
        }
        if (success) {
            rename("out.dat", "in.dat"); /* Good */
        }
    #endif
        return EXIT_SUCCESS;
    }