62

我阅读了一系列关于C++11中新标头的深思熟虑的博客文章。<system_error>它表示标头定义了一个error_code类,该类表示操作(例如系统调用)返回的特定错误值。它说头部定义了一个system_error类,它是一个异常类(继承自runtime_exception),用于包装error_codess。

我想知道的是如何将系统错误从实际转换errno为 asystem_error以便我可以抛出它。例如,POSIXopen函数通过返回 -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;,但我想以正确的方式做,使用新的<system_error>标题。

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

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

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

4

2 回答 2

61

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

例子:

#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 - 错误地址
于 2012-08-29T05:48:29.397 回答
6

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

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
于 2021-04-18T20:07:22.240 回答