为什么 C++ STL iostreams 不“异常友好”?

发布于 2024-09-08 09:23:09 字数 374 浏览 4 评论 0原文

我习惯了 Delphi VCL 框架,其中 TStream 会在错误时抛出异常(例如,文件未找到、磁盘已满)。我正在移植一些代码以使用 C++ STL,并且被 iostreams 发现,默认情况下不抛出异常,但设置 badbit/failbit 标志 代替。

有两个问题...

a:为什么会这样 - 对于从第一天起就包含异常的语言来说,这似乎是一个奇怪的设计决策?

b:如何最好地避免这种情况?我可以生成按照我的预期抛出的垫片类,但这感觉就像重新发明轮子。也许有一个 BOOST 库可以以更理智的方式做到这一点?

I'm used to the Delphi VCL Framework, where TStreams throw exceptions on errors (e.g file not found, disk full). I'm porting some code to use C++ STL instead, and have been caught out by iostreams NOT throwing exceptions by default, but setting badbit/failbit flags instead.

Two questions...

a: Why is this - It seems an odd design decision for a language built with exceptions in it from day one?

b: How best to avoid this? I could produce shim classes that throw as I would expect, but this feels like reinventing the wheel. Maybe there's a BOOST library that does this in a saner fashion?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寄与心 2024-09-15 09:23:09
  1. C++ 从第一天起就没有例外。 “带有类的 C”始于 1979 年,并于 1989 年添加了例外。同时,streams 库早在 1984 年就已编写(后来在 1989 年成为 iostreams(后来重新实现) GNU 在 1991 年)),它只是不能在一开始就使用异常处理。

    参考:

  2. 可以使用 .exceptions 方法

// ios::exceptions
#include <iostream>
#include <fstream>
#include <string>

int main () {
    std::ifstream file;
    file.exceptions(ifstream::failbit | ifstream::badbit);
    try {
        file.open ("test.txt");
        std::string buf;
        while (std::getline(file, buf))
            std::cout << "Read> " << buf << "\n";
    }
    catch (ifstream::failure& e) {
        std::cout << "Exception opening/reading file\n";
    }
}
  1. C++ wasn't built with exceptions from day one. "C with classes" started in 1979, and exceptions were added in 1989. Meanwhile, the streams library was written as early as 1984 (later becomes iostreams in 1989 (later reimplemented by GNU in 1991)), it just cannot use exception handling in the beginning.

    Ref:

  2. You can enable exceptions with the .exceptions method.

// ios::exceptions
#include <iostream>
#include <fstream>
#include <string>

int main () {
    std::ifstream file;
    file.exceptions(ifstream::failbit | ifstream::badbit);
    try {
        file.open ("test.txt");
        std::string buf;
        while (std::getline(file, buf))
            std::cout << "Read> " << buf << "\n";
    }
    catch (ifstream::failure& e) {
        std::cout << "Exception opening/reading file\n";
    }
}
滥情稳全场 2024-09-15 09:23:09

好的,现在是“回答我自己的问题”时间...

首先,感谢 KennyTM 提供的历史记录。正如他所说,C++ 从第一天起就没有设计出异常,因此后来添加了 iostreams“异常”处理也就不足为奇了。

其次,正如 Neil B 指出的那样,输入格式转换错误出现异常将是一个巨大的痛苦。这让我感到惊讶,因为我将 iostreams 视为一个简单的文件系统包装层,而我根本没有考虑过这种情况。

第三,看来 BOOST 确实给聚会带来了一些东西: Boost.IOStreams。如果我理解正确的话,它们处理流的低级 I/O 和缓冲方面,而让常规的 c++ IOStreams 库来处理转换问题。 Boost.IOStreams 确实使用异常以我所期望的方式。如果我理解正确的话,肯尼的例子也可能是这样的:

#include <ostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/stream.hpp>

int main () {
  boost::iostreams::stream_buffer <boost::iostreams::file_source> buf("test.txt");
  std::istream file(&buf);

  try {
    std::string buf;
    while (std::getline(file, buf))
      std::cout << "Read> " << buf << "\n";
  }
  catch (std::ios_base::failure::failure e) {
    std::cout << "Exception opening/reading file\n";
  }

  return 0;
}

认为在这个版本中,应该抛出“文件未找到”之类的错误,但“istream”错误将由 badbit/failbit 报告。

OK, it's "Answer my own question" time...

First, thanks to KennyTM for the history. As he says, C++ was NOT designed with exceptions from day one, so it's unsurprising that iostreams 'exception' handling was bolted on afterwards.

Second, as Neil B points out, having exceptions on input format conversion errors would be a significant pain. This surprised me, because I was considering iostreams as a simple filesystem wrapper layer, and I hadn't considered that case at all.

Third, it appears BOOST does bring something to the party: Boost.IOStreams. If I understand correctly, these handle the low-level I/O and buffering aspect of streams, leaving the regular c++ IOStreams library to handle conversion issues. Boost.IOStreams does use exceptions in the way I'd expect. If I understand it correctly, Kenny's example could also look like this:

#include <ostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/stream.hpp>

int main () {
  boost::iostreams::stream_buffer <boost::iostreams::file_source> buf("test.txt");
  std::istream file(&buf);

  try {
    std::string buf;
    while (std::getline(file, buf))
      std::cout << "Read> " << buf << "\n";
  }
  catch (std::ios_base::failure::failure e) {
    std::cout << "Exception opening/reading file\n";
  }

  return 0;
}

I think with this version, things like "file not found" should throw, but 'istream' errors will be reported by badbit/failbit.

痴者 2024-09-15 09:23:09

正如肯尼所说,如果您愿意,您可以启用例外。但通常 I/O 在发生错误时需要某种恢复风格的编程,而使用异常不容易支持这一点 - 在输入操作后测试流的状态要简单得多。我实际上从未见过任何在 I/O 上使用异常的 C++ 代码。

As Kenny says, you can enable exceptions if you want. But normally I/O requires some sort of resumption style of programming when an error occurs, which is not easily supported by using exceptions - testing the state of the stream after an input operation is much simpler. I've never actually seen any C++ code that uses exceptions on I/O.

饮惑 2024-09-15 09:23:09
  1. 每当抛出异常时,您都需要考虑异常安全。所以没有异常,没有异常,没有异常安全头痛。

  2. Iostream 还支持异常。但抛出异常是可选的。您可以通过设置异常(failbit | badbit | eofbit)

    来启用异常,

  3. Iostreams 让您同时接受异常和无期望行为。

  1. Whenever you throw an exception you need to think about exception safety. So no exception, no exception, no exception-safety headache.

  2. Iostreams also support exceptions. But throwing an exception is optional. You can enable exception by setting exceptions (failbit | badbit | eofbit)

  3. Iostreams let you entertain both exception and expection-less behavior.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文