c++ - 在 C++ 中创建文件时如何获取 IO 错误消息?

标签 c++ c++11 exception exception-handling io

古老的反模式之一是人们检查错误状态,然后返回相当无用的消息,例如“操作失败”而不是“操作失败,因为...”。我希望 C++ 文件 I/O 操作因异常而失败,并获得有关失败原因的错误消息。具体来说,我希望 ofstream 对象在文件创建失败时引发异常并获得更有用的消息,例如“权限被拒绝”或“无文件或路径”。

这在 C# 或 Java 或 Python 等语言中是微不足道的,但不知怎的,没有很好的文档记录方法来完成这个 C++。默认情况下,iostream 对象只是默默地失败。有一些全局错误代码,但我宁愿有异常(exception)。经过大量搜索,我了解到您可以使用以下代码行启用异常:

my_file.exceptions(flog.exceptions() | std::ios::failbit | std::ifstream::badbit);

这行得通,但现在引发的异常是 std::ios_base::failure 并且 ex.what() 返回无用的字符串,如“basic_ios::clear”。根据 C++11 规范,std::ios_base::failure 应该继承自 system_error,后者具有 .code().message() 将给出异常消息。让我们在这里把这种怪异放在一边,而不是指责决定 what() 不应该返回实际错误消息的人:)。问题是,即使在使用 C++11 和 G++ 4.8.4 进行编译时,我发现 std::ios_base::failure 实际上并不是从 system_error 继承的。

问题

  1. 为什么 std::ios_base::failure 不是从最新的 G++ 4.8.4 中的 system_error 继承的,即使在使用 C++11 模式编译时也是如此? GCC 在这方面对 C++11 的实现是不完整的,还是我需要做更多的事情?
  2. 当 IO 操作在 C++ 中失败并收到错误消息时,如何实现引发异常的目标?即使在最新的 C++11 或 C++14 中也没有办法做到这一点吗?有哪些替代方案?

这是示例代码。你可以compile and run it here .

#include <iostream>
#include <fstream>
#include <system_error>

int main() {
    try {
        std::ofstream flog;
        flog.exceptions(flog.exceptions() | std::ios::failbit | std::ifstream::badbit);
        flog.open("~/watever/xyz.tsv", std::ios::trunc);
    }
    catch (const std::ios_base::failure &ex) {    
        std::cout << "ios_base::failure: " << ex.what();
    }
    catch(const std::system_error& ex) {
        std::cout << "system_error: " << ex.code().message();
    }
}

最佳答案

  1. 根据 GCC 的 C++11 status documentation , 完全支持“系统错误支持”。

    并根据Bug 57953 - no C++11 compliant std::ios_base::failure found , std::ios_base::failure 已在 Revision 217559 中更改从 C++11 中的 system_error 派生。如果您查看更新后的 ios_base.hstd::ios_base::failure 派生自 system_error if _GLIBCXX_USE_CXX11_ABI被定义为。 GCC 的 Using Dual ABI 中提到了该定义文档。

    但是,由于标准库的某些部分未定义 _GLIBCXX_USE_CXX11_ABI,因此仍然存在关于 std::ios_base::failure 的 ABI 问题的回归:

    Bug 66145 - [5/6/7 Regression] std::ios_base::failure objects thrown from libstdc++.so use old ABI

  2. 简短的回答是 - 您可能不能,至少在 GCC 当前的实现中不能。除非您可以使用定义的 _GLIBCXX_USE_CXX11_ABI 重新编译库中的所有内容。

关于c++ - 在 C++ 中创建文件时如何获取 IO 错误消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38471518/

相关文章:

c++ - 堆损坏,可能的内存泄漏,C++

c++ - std::swap between std::shared_ptr<A> 其中 A 具有动态数组

Android - 图像加载器错误

multithreading - 将托管 .NET 客户端设置为使用 STA 线程是否有任何原因会导致 native COM 服务器中出现异常问题?

c# - 使用 control.BackgroundImage = Image.FromStream(memStream) 时出现内存不足异常;

c# - 在程序中运行 gcc 的安全、跨平台方式

c++ - C++ 的 Makefile 入门(CMake 或 GNUMake?)

c++ - 在无尽的跑酷游戏中处理大的 x 值

c++ - 位域的完美转发解决方法

c++11 - 在 C++11 中,我可以在显式默认析构函数上使用重写说明符吗?