stdio错误检测:错误与fclose

问题描述 投票:4回答:1

在标准C中,如何可靠地检查所有写入标准I / O流的输出是否已成功保存到磁盘?

C标准指出,fclose成功返回0,如果“检测到任何错误”,则返回EOF。

但这是否意味着“在fclose通话期间检测到任何错误”?还是说“自上次调用clearerr以来检测到任何错误”?

换句话说,对于程序来说,[[just检查fclose的返回值是否足够?还是需要检查ferror?是否有任何实现方式,如果ferror返回非零,则随后对fclose的调用可能返回0?

fflush的情况也一样:如果fflush返回0,则对ferror的后续调用也会返回0,如果fflush返回EOF,则对ferror的后续调用总是这样会返回非零值吗?有没有不是这种情况的实现?

((当然,我不考虑停电,gremlins等。是的,要求保证耐用性的程序应使用fsync,但这不在标准C的范围内。)

c language-lawyer stdio
1个回答
2
投票
没有更好的答案:

  • 标准告诉我ferror()返回定义为

    stream状态一部分的“错误指示符”的状态。

  • 标准告诉了我很多关于何时设置“错误指示符”的信息,但是关于何时清除该错误的信息不多-除了定义了clearerr()rewind()

    are]来清除它之外。

  • 如果调用函数时设置了“错误指示符”,则标准不告诉我任何功能(ferror()除外)的预期作用。
  • 您的问题似乎是基于一旦有错误就设置“错误指示器”的可能性,并且仅在明确清除(“锁定”)后才清除。在这种情况下:

  1. [ferror()会告诉您,自fopen()(或最近的clearerr()rewind())以来,某些stdio函数中发生了错误。

    我不认为标准有此要求,但没有说可能没有。

  2. [fclose()可能会返回错误(a),如果在关闭时发生错误;

    or

  3. (b)如果已经设置了“错误指示符”。并且,如果是这样,则成功的fclose()表示自fopen()(或最近的clearerr()rewind())以来一切都很好。

    我不认为标准有此要求,但没有说可能没有。

    如果标准没有明确要求某些东西,也没有明确排除某些东西,我们就有一只既不活也不死的猫。

    简而言之,我认为标准无法以一种或另一种方式回答您的任何问题。

对该标准的保守解读为:

  • 在每次stdio函数调用后立即检查错误,并相应地进行。

  • 通常,在发生读取或写入错误之后,放弃和关闭流是显而易见的响应。

    fclose()可能会返回当前错误(再次),或者返回新错误或根本没有错误。如果要返回错误,我将返回原始的读/写错误。在要报告错误的地方,我将报告原始的读/写错误和fclose()返回的任何错误。

  • 如果决定继续输入/输出,则“错误指示符”可能(或可能不会)影响其他功能,并且可能(或可能不会)由其他更多功能清除...

    ...因此最好清除clear(),以避免任何可能的混乱。

  • 但是,我几乎确信fgetc()必须:

    a。如果已经设置了“错误指示符”,则立即放弃(并再次设置errno

    或:

    b。清除“错误指示符”-如果不是,那么fgetc()然后成功并返回EOF是什么意思?

    其他get和put char和wide-char也是如此。对于返回值不是模棱两可的所有其他函数,情况并非如此。

  • 不希望ferror()告诉您有关最近的stdio函数调用之前可能发生的错误的任何信息。

    很明显,ferror()对于错误返回与EOFWEOF返回相同的少数功能很有用。 (如果可能出现feof()EOF值的字符,则WEOF很有用!)。

    尚不清楚ferror()和“错误指示符”是否对其他有用。


  • FWIW:我在标准中发现的内容

    [标准说(§7.21.7.1)对于fgetc()

    如果未设置流指向的输入流的文件结尾指示符,并且存在下一个字符,则fgetc函数将获得该字符作为转换为int的无符号字符,并前进关联的文件位置流的指示器(如果已定义)。
  1. 返回

      如果设置了流的文件结束指示符,或者流位于文件末尾,则设置了流的文件结束指示符,并且fgetc函数返回EOF 。否则,fgetc函数从流指向的输入流中返回下一个字符。如果发生读取错误,则设置流的错误指示符,并且fgetc函数返回EOF
    1. 293)

    293]可以通过使用feofferror函数来区分文件结束和读取错误。

我注意到,如果在调用函数时设置了“文件结束指示符”,应该怎么做就很清楚了。相反,它没有说,如果已经设置了“错误指示符”,则fgetc()应该做什么:

  1. fgetc()应该立即失败吗?

    如果是这样,是否应该将errno设置为与首次设置“错误指示符”时相同的值?

但是,如果“错误指示符”先前是由(例如)EINTR设置的,则无须理会它。

否则:

  1. [如果调用成功,fgetc()应该清除'错误指示符'吗?
  2. 如果没有,则“错误指示符”可以被认为是“锁定”状态,表示自上次清除错误指示符以来的某个时间,发生了错误。

同样,如果“错误指示器”先前是由(例如)EINTR设置的,则将其设置为无意义。请注意,C对EINTR一无所知...因此,实现可以自由地对“错误指示器”执行不同的操作,具体取决于它的设置方式。]

AND

,如果fgetc()刚好正好获取值EOF的字符或恰好碰到了实际的EOF,则NOT清除“错误指示符”将是一个错误! [标准说(§7.21.7.3)对于fputc()

    fputc函数将由c指定的字符(转换为无符号字符)写入输出流...
  1. 返回

    fputc函数返回写入的字符。如果发生写错误,则设置流的错误指示符,并且fputc返回EOF
  • 同样,如果没有设置'错误指示符',这并没有指定fputc()应该做什么。

    [fgetwc()fputwc()同样。

  • [定义了所有其他输入/输出功能,就像它们在重复fgetc()fputc()fgetwc()和fputwc()中一样工作。

    [标准规定(§7.21.10.3)表示ferror()

      ferror函数测试流所指向的流的错误指示符。
    1. 返回

        [且仅当为流设置了错误指示符时,ferror函数返回非零。
  • 就是这样。上面的脚注

    293

    是有关如何使用ferror()和“错误指示器”的最具体指南。
  • fflush()(§7.21.5.2),fseek()(§7.21.9.2)和fsetpos()(§7.21.9.3)均已定义为在发生错误时设置“错误指示符”。

    rewind()(第7.2.1.9.5节)和clearerr()(第7.2.10.1节)被定义为清除“错误指示符”。

    我没有找到对“错误指示器”的其他引用。

    © www.soinside.com 2019 - 2024. All rights reserved.