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

Dav*_*son 52 c++ exception c++11

我在C++ 11中阅读了一系列关于新<system_error>标题的深思熟虑的博客文章.它表示标头定义了一个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 */;
    }
}
Run Code Online (Sandbox Code Playgroud)

我随机试了一下:

errno = ENOENT;
throw std::system_error();
Run Code Online (Sandbox Code Playgroud)

但是在what()调用时,结果异常不返回任何信息.

我知道我可以做throw errno;但我想以正确的方式使用新的<system_error>标题.

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

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

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

Som*_*ude 53

你是在正确的轨道,只是将错误代码和一个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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我系统上面程序的输出是

Error: generic:14 - Bad address

  • 你不能只抛出`std :: system_error(EFAULT,std :: system_category());` (4认同)
  • 对于遇到同样问题的其他人,我发现`error.what()`返回一个空字符串但是`error.code().message()`返回一个很好的字符串. (3认同)
  • @IInspectable在POSIX系统上,我认为那些错误代码*来自操作系统.确实有些错误可能来自实用程序函数或C库函数,但它们也可能来自*系统调用*,如`write`和`socket`. (2认同)
  • 又一个 C++ 错误...对于这样一个常见的任务来说,界面多么混乱啊! (2认同)

rus*_*tyx 13

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

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);
}
Run Code Online (Sandbox Code Playgroud)

然后当被捕获时,e.what()将返回,例如:

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);
}
Run Code Online (Sandbox Code Playgroud)