aka*_*jkn 5 c++ qt exception-handling
我正在为使用 qtestlib、C++(clang LLVM 8.0 版)读取文件编写单元测试。我有以下代码用于逐行读取文件。
std::ifstream infile;
try {
    infile.open(path.c_str());
    std::ios_base::iostate exceptionMask = infile.exceptions() | std::ios::failbit;
    infile.exceptions(exceptionMask);
} catch (std::ios_base::failure& e) {
    // print the exception
    qDebug() << "Exception caught: " << QString::fromStdString(e.what());
}
try {
    std::string line;
    while (std::getline(infile, line)) {
        // print the line
        qDebug() << QString::fromStdString(line);
    }
} catch (std::ios_base::failure& e) {
    qDebug() << "Exception caught: " << QString::fromStdString(e.what());
}
问题:
上面的代码读取文件中的所有行并打印出来。但是在打印最后一行后,它抛出异常并打印以下内容,
捕获异常:“basic_ios::clear”
我关注了很多线程,但找不到解决方案。为什么我收到这个错误?
阅读并打印所有行后,系统while (std::getline(infile, line))仍会尝试读取另一行。如果它完全失败 - 读取零字符 - 它会发出failbit失败信号。
错误消息的奇怪部分是,尽管它的名称如此,但它basic_ios::clear可以用于设置故障位,并且如果您使用 启用了相同的位,也会引发异常exceptions。
查看std::getline的文档。关于设置标志的部分:
故障位
获得的输入无法解释为该类型对象的有效文本表示。在这种情况下, distr保留调用之前的参数和内部数据。请注意,某些eofbit情况也会设置failbit。
最后一句话有点模糊,但可以解释观察到的行为。
我做了一些实验并发现了规律。首先我这样更正了你的代码:
try {
    std::string line;
    while (std::getline(infile, line)) {
        // print the line
        qDebug() << QString::fromStdString(line);
        if (infile.eof()) {
            return;
        }
    }
} catch (std::ios_base::failure& e) {
    qDebug() << "Exception caught: " << QString::fromStdString(e.what());
}
现在,如果输入文件以空行结尾,我会得到一个异常,如果最后一行不以“\n”结尾,return则会中断循环。
因此,如果您尝试读取已经到达流末尾的流,则会设置falbit 。如果没有“if”检查,您总是在进行此读取,并且总是会遇到异常。
对于最后一行空我有一些线索,但不知道如何很好地解释它。首先必须检查其他平台/编译器的行为。