如何使用<system_error> </system_error>将errno转换为异常

时间:2012-08-29 05:24:20

标签: c++ exception c++11

我读了一篇关于C ++ 11中新<system_error>标题的深思熟虑的series of blog posts。它表示标头定义了一个error_code类,它表示操作返回的特定错误值(例如系统调用)。它表示标头定义了一个system_error类,它是一个异常类(继承自runtime_exception)并用于包装error_codes

我想知道的是如何将系统错误从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;但我想以正确的方式使用新的<system_error>标题。

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

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

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

2 个答案:

答案 0 :(得分:53)

您走在正确的轨道上,只需将错误代码和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);
    }
}

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

Error: generic:14 - Bad address

答案 1 :(得分: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