Как преобразовать errno в исключение, используя <system_error>
Я прочитал вдумчивую серию постов в блоге о новом <system_error>
заголовок в C++11. Он говорит, что заголовок определяет error_code
класс, представляющий конкретное значение ошибки, возвращаемое операцией (такой как системный вызов). Он говорит, что заголовок определяет system_error
класс, который является классом исключения (наследуется от runtime_exception
) и используется для упаковки error_codes
s.
То, что я хочу знать, это как на самом деле конвертировать системную ошибку из 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
тогда все остальное должно быть очевидным.
Это кажется очень простой вещью, поэтому я не знаю, почему я не могу найти хороший учебник по этому вопросу.
Я использую gcc 4.4.5 на процессоре ARM, если это имеет значение.
2 ответа
Вы на правильном пути, просто передайте код ошибки и 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 - неверный адрес
Чтобы добавить к отличному принятому ответу, вы можете дополнить сообщение об ошибке некоторой контекстной информацией в третьем аргументе, например, неудачным именем файла:
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