gpt4 book ai didi

c - stdio 错误检测 : ferror versus fclose

转载 作者:行者123 更新时间:2023-12-04 11:26:52 28 4
gpt4 key购买 nike

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

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

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

换句话说,程序只检查 fclose 的返回值是否足够? ,还是还要查ferror ?是否有任何实现,如果 ferror返回非零值,随后调用 fclose可能返回0?
fflush 也是如此: 如果 fflush 总是这样吗?返回 0,随后调用 ferror也会返回 0,如果 fflush返回 EOF,随后调用 ferror会返回非零吗?是否有任何实现不是这种情况?

(当然,我不考虑停电、小鬼等。是的,需要保证持久性的程序应该使用 fsync ,但这超出了标准 C 的范围。)

最佳答案

在没有更好的答案的情况下:

  • 标准告诉我 ferror()返回定义为流状态一部分的“错误指示器”的状态。
  • 该标准告诉我很多关于何时设置“错误指示器”的信息,但没有关于何时可以清除的信息——除了 clearerr()rewind()被定义为清除它。
  • 如果在调用函数时设置了“错误指示器”,标准没有告诉我任何函数(除了 ferror() 之外)应该做什么。

  • 您的问题似乎基于这样一种可能性,即一旦出现错误就会设置“错误指示器”,并且仅在明确清除(“锁定”)时才清除。在这种情况下:
  • ferror()会告诉你在某些 stdio 函数中发生了错误,因为 fopen() (或最近的 clearerr()rewind() )。

    我不认为标准要求这样做,但它并没有说可能不需要。
  • fclose()可能会返回错误 (a) 如果在关闭时发生,或者 (b) 如果“错误指示器”已经设置。

    并且,如果是这样,则成功 fclose()这意味着一切都很好,因为 fopen() (或最近的 clearerr()rewind() )。

    我不认为标准要求这样做,但它并没有说可能不需要。

  • 在标准没有明确要求某些东西并且没有明确排除某些东西的地方,我们有一只既不活也不死的猫。

    简而言之,我认为标准不会以某种方式回答您的任何问题。

    对该标准的保守解读是:
  • 在每次 stdio 函数调用后立即检查错误,并相应地进行。
  • 通常,在读取或写入错误后,放弃并关闭流是显而易见的响应。
    fclose()可能会返回当前错误(再次),或新错误或根本没有错误。如果要返回错误,我将返回原始读/写错误。如果要报告错误,我将报告原始读/写错误和 fclose() 返回的任何错误。 .
  • 如果决定继续输入/输出,则“错误指示器”可能(或可能不会)影响其他功能,并且可能(或可能不会)被大多数其他功能清除......

    ...所以最好是 clearerr(),以避免任何可能的混淆。

    然而,我几乎确信fgetc()必须:

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

    或者:

    湾清除“错误指示器”——如果没有,如果 fgetc() 意味着什么然后成功并返回 EOF ?

    其他 get 和 put 字符和宽字符也是如此。对所有其他函数来说并非如此,其中返回值没有歧义。
  • 没想到ferror()告诉您有关在最近的 stdio 函数调用之前可能发生的错误的任何信息。

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

    不太清楚ferror()并且“错误指示器”可用于其他任何事情。


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

    标准说(第 7.21.7.1 节)对于 fgetc() :

    1. If the end-of-file indicator for the input stream pointed to by stream is not set and a next character is present, the fgetc function obtains that character as an unsigned char converted to an int and advances the associated file position indicator for the stream (if defined).

    Returns

    1. If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF. Otherwise, the fgetc function returns the next character from the input stream pointed to by stream. If a read error occurs, the error indicator for the stream is set and the fgetc function returns EOF 293).

    293) An end-of-file and a read error can be distinguished by use of the feof and ferror functions.



    我注意到,如果在调用函数时设置了“文件结束指示符”,它应该做什么是非常清楚的。相比之下,它并没有以某种方式说明什么 fgetc()如果已经设置了“错误指示器”,应该这样做:
  • 应该fgetc()立即失败?

    如果是这样,是否应该设置errno与第一次设置“错误指示器”时的值相同?

    但是,如果“错误指示器”先前由(例如)EINTR 设置,去注意它是没有意义的。

  • 除此以外:
  • 应该fgetc()如果此调用成功,清除“错误指示器”?

    如果不是,则“错误指示器”可以被认为是“锁定”状态,表明自它上次清除以来的某个时间,发生了错误。

    同样,如果“错误指示器”先前由(例如)EINTR 设置,让它设置是没有意义的。请注意,C 对 EINTR 一无所知...所以实现可以自由地使用“错误指示器”做不同的事情,这取决于它是如何设置的。

    并且,如果 fgetc()恰好获取了一个值为 EOF 的字符或者碰巧碰到了实际的 EOF,那么不清除“错误指示器”将是一个错误!

  • 标准说(第 7.21.7.3 节)对于 fputc() :

    1. The fputc function writes the character specified by c (converted to an unsigned char) to the output stream ...

    Returns

    1. The fputc function returns the character written. If a write error occurs, the error indicator for the stream is set and fputc returns EOF.


    再一次,这并没有指定什么 fputc()如果已经设置了“错误指示器”,则应该这样做。

    这同样适用于 fgetwc()fputwc() .

    每个其他输入/输出函数都被定义为“好像”它们被重复 fgetc() , fputc() , fgetwc()和 fputwc()`。

    标准说(第 7.21.10.3 节)对于 ferror() :

    1. The ferror function tests the error indicator for the stream pointed to by stream.

    Returns

    1. The ferror function returns nonzero if and only if the error indicator is set for stream.


    就是这样。上面的脚注 293 是我们所拥有的最具体的指南 ferror()并且应该使用“错误指示器”。
    fflush() (第 7.21.5.2 节), fseek() (第 7.21.9.2 节)和 fsetpos() (第 7.21.9.3 节)都定义为在发生错误时设置“错误指示器”。
    rewind() (第 7.21.9.5 节)和 clearerr() (第 7.21.10.1 节)被定义为清除“错误指示器”。

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

    关于c - stdio 错误检测 : ferror versus fclose,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61828953/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com