【问题标题】:do I need to close a std::fstream? [duplicate]我需要关闭 std::fstream 吗? [复制]
【发布时间】:2011-06-15 16:58:47
【问题描述】:

可能重复:
Do I need to manually close a ifstream?

我需要调用fstream.close() 还是fstream 是一个适当的RAII 对象,可以在销毁时关闭流?

我在方法中有一个本地 std::ofstream 对象。我可以假设退出此方法后文件总是关闭而不调用close吗?我找不到析构函数的文档。

【问题讨论】:

  • 是的,它是重复的。谢谢你。我没找到。
  • 不是完全重复的。引用的问题是针对 ifstreams 的,而这个问题一般是关于 fstreams 的。
  • "我需要关闭一个 std::fstream 吗?"并在答案中说“8年前关闭。”

标签: c++ std fstream ofstream


【解决方案1】:

我认为之前的答案具有误导性。

fstream 一个合适的 RAII 对象,它确实在作用域结束时自动关闭,绝对没有任何需要 在作用域结束时手动调用close 就足够了。

特别是,这不是“最佳实践”,也没有必要刷新输出。

虽然 Drakosha 是正确的,调用 close 可以让您检查流的失败位,但无论如何没人这样做。

在理想情况下,只需事先调用stream.exceptions(ios::failbit) 并处理fstream 的析构函数中抛出的异常。但不幸的是,析构函数中的异常在 C++ 中是一个错误的概念,所以这不是一个好主意。

所以如果您想检查关闭文件是否成功,请手动执行(但仅在那时)。

【讨论】:

  • 我实际上每次都检查关闭结果,因为我正在开发一个必须确保将数据提交到磁盘的应用程序。此外,有点不合时宜,close 不能确保刷新(至少在 linux 上),而且我不确定析构函数是否刷新。我实际上会说冲洗和关闭是“最佳实践”,并检查两者的错误。
  • @Drakosha:确保数据一直刷新到磁盘与flushclose 所保证的完全不同。一般来说,您可以假设的最好的是flush 将数据从进程中获取并进入操作系统级别,例如杀死进程不会阻止数据被写入。没有可移植的 API 来确保将数据提交到持久存储,因为 C++ 标准没有持久存储的概念,而不是作为文件系统(的一部分)呈现的其他存储。
  • 我也对这种 linux 行为感到有些惊讶。 fstream 析构函数需要调用close 成员函数,close 需要关闭“如同fclose”,而fclose 被定义为刷新流。所以析构函数当然应该冲洗,尽管如果存在插头被拉到机器上的风险,冲洗可能不一定能达到你想要的效果。为此,您需要(非标准 C++)fsync
  • @Highstaker 在自动完成的编程中手动做事绝对是个坏习惯。在这种特殊情况下,它碰巧没有不良影响(除了添加了无意义的代码行),但这并不是一个很好的原则。
  • @jrh 在断开连接后关闭外部存储介质上的文件。这将导致关闭(和刷新)失败,但应用程序可以成功继续运行。
【解决方案2】:

要附加到 Amy Lee 的答案,最好手动执行,因为这样您也可以检查错误。

顺便说一句,根据"close" manpage

不检查返回值 close() 是一个常见的但仍然 严重的编程错误。这是很 可能是以前的错误 write(2) 操作先上报 在最后关闭()。不检查 关闭文件时的返回值可能 导致数据无声丢失。这个可以 尤其是在 NFS 和 有磁盘配额。

成功关闭并不能保证 数据已经成功 保存到磁盘,因为内核延迟 写道。这并不常见 文件系统在什么时候刷新缓冲区 流已关闭。如果你需要 确保数据在物理上 存储使用 fsync(2)。 (这将取决于 此时在磁盘硬件上。)

【讨论】:

  • 最好手动如果你需要检查错误,这并不意味着我们应该总是手动关闭。您不能从例外情况中得出一般做法。在一般情况下,当它关闭时,我们并不关心它是如何成功的,所以让它自动关闭。
  • @GMan:如果你不检查错误,这意味着你在误导用户,数据在磁盘上,而实际上不在。
  • @Drakisha:但就像史蒂夫说的那样,一旦我关闭(这是自动完成的),错误与否都不是我能控制的。此外,您的“增强”是非标准 C++,我们在这里谈论的是标准 fstream C++。
  • @GMan:这不是你能控制的,这取决于上下文。至少你应该让你的用户知道。
  • 这是一个糟糕的答案。 close() 不是 fstream::close()。根据规范,后者将始终刷新。在网上很容易找到。
【解决方案3】:

我认为关闭 fstream 是一个好习惯,因为你需要刷新缓冲区,这是我被告知的

【讨论】:

  • 如果 fstream 是一个 RAII 对象,它将被关闭,因此无论如何都会刷新缓冲区。主要问题是我是否需要对所有控制流进行错误处理以确保它被刷新。
  • 抱歉,-1 只是因为它有 +2。手动释放资源要么是不良编程的标志,要么是对容器用途的误解。
  • @GMan:我认为不关心您的文件是否正确关闭是例外情况,在大多数情况下您应该自己致电close()太多的软件开发人员假设我宁愿他们不考虑用户文件系统的可靠性和可用性。
  • @GManNickG 在另一个答案上见my comment;任何可以选择写入可能不可靠或可移动的媒体(例如闪存驱动器、网络驱动器)的程序都应该手动关闭,以便您可以通知用户保存失败和/或让他们选择不同的位置.
猜你喜欢
  • 2013-01-10
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 2017-07-10
  • 2010-10-19
  • 2021-02-24
  • 2018-07-24
  • 1970-01-01
相关资源
最近更新 更多