【问题标题】:How to convert errno to exception using <system_error>如何使用 <system_error> 将 errno 转换为异常
【发布时间】:2012-08-23 16:13:51
【问题描述】:

我阅读了一篇关于 C++11 中新的 &lt;system_error&gt; 标头的深思熟虑的 series of blog posts。它表示标头定义了一个error_code 类,该类表示操作(例如系统调用)返回的特定错误值。它说头部定义了一个system_error类,这是一个异常类(继承自runtime_exception),用于包装error_codess。

我想知道的是如何将系统错误从errno 实际转换为system_error,以便我可以抛出它。比如POSIX的open函数通过返回-1并设置errno来报错,那么如果我想抛出异常我应该如何完成下面的代码呢?

void x()
{
    fd = open("foo", O_RDWR);
    if (fd == -1)
    {
        throw /* need some code here to make a std::system_error from errno */;
    }
}

我随意尝试:

errno = ENOENT;
throw std::system_error();

但是当调用what() 时,产生的异常不会返回任何信息。

我知道我可以使用throw errno;,但我想以正确的方式使用新的&lt;system_error&gt; 标头。

system_error 有一个构造函数,它接受一个 error_code 作为其参数,所以如果我可以将 errno 转换为 error_code,那么其余的应该是显而易见的。

这似乎是一个非常基本的东西,所以我不知道为什么我找不到一个好的教程。

我在 ARM 处理器上使用 gcc 4.4.5,如果这很重要的话。

【问题讨论】:

    标签: c++ exception c++11


    【解决方案1】:

    您在正确的轨道上,只需将错误代码和std::generic_category 对象传递给std::system_error constructor,它应该可以工作。

    例子:

    #include <assert.h>
    #include <errno.h>
    #include <iostream>
    #include <system_error>
    
    int main()
    {
        try
        {
            throw std::system_error(EFAULT, std::generic_category());
        }
        catch (std::system_error& error)
        {
            std::cout << "Error: " << error.code() << " - " << error.what() << '\n';
            assert(error.code() == std::errc::bad_address);
        }
    }
    

    上述程序在我的系统上的输出是

    错误:通用:14 - 错误地址

    【讨论】:

    • 酷,行得通!出于某种原因,在我的系统上,完全相同的代码只输出“错误:系统:14 - ”但我可能没有使用最新版本的 libstdc++ 或其他东西。
    • 对于其他有同样问题的人,我发现error.what() 返回一个空字符串,但error.code().message() 返回一个不错的字符串。
    • 你不能直接扔std::system_error(EFAULT, std::system_category());
    • 要包装 POSIX errno 代码,请使用 std::generic_categorystd::system_category 用于处理操作系统报告的错误。
    • @IInspectable 在 POSIX 系统上,我认为那些错误代码 来自操作系统。当然有些错误可能来自实用程序函数或 C 库函数,但它们也可能来自 系统调用,例如 writesocket
    【解决方案2】:

    要添加到公认的优秀答案,您可以在第三个参数中使用一些上下文信息来丰富错误消息,例如失败的文件名:

    std::string file_name = "bad_file_name.txt";
    fd = open(file_name, O_RDWR);
    if (fd < 0) {
        throw std::system_error(errno, std::generic_category(), file_name);
    }
    

    那么当被捕获时,e.what() 会返回,例如:

    bad_file_name.txt: file not found
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 2018-05-20
      • 1970-01-01
      • 2011-06-02
      • 2017-09-19
      • 2014-04-11
      相关资源
      最近更新 更多