C++ 11异常设计.成语和最佳实践发生了变化?

Ger*_*ago 21 c++ exception-handling c++11

我想知道,自从C++ 11以来,添加了线程之间的异常并添加了嵌套异常,一般来说,异常捕获的习语是否已更改.

现在我们有:

  1. std::rethrow_if_nested
  2. std::rethrow_with_nested
  3. std::rethrow_exception
  4. std::current_exception

嵌套异常应该用于不丢失异常的上下文.

所以现在你可以这样做:

void open_file(std::string const & file_name) {
   try {
      std::ifstream file;
      file.exceptions(ios::failbit | ios::badbit);
      file.open(file_name);
   }
   catch (...) {
      std::rethrow_with_nested(std::logic_error("File " + file_name + 
      " could not be open"));
   }
}
Run Code Online (Sandbox Code Playgroud)

如果我没错,你可以得到这样的回溯:

void print_backtrace(std::exception const & e, int depth = 0) {
   std::cerr << std::string(depth, ' ') << e.what() << std::endl;
   try {
      std::rethrow_if_nested(e);
   }
   catch (std::exception const & ex) {
      print_backtrace(ex, ++depth);
   }
}
Run Code Online (Sandbox Code Playgroud)

所以,如果你使用print_backtraceopen_file它应该给你std::logic_error+的ios_base::failure输出.

我的问题是:

  1. 这个习惯用法是在c ++ 11中处理异常的"正确"方法,因为我想在不丢失上下文的情况下捕获所有异常吗?
  2. print_backtrace函数中是否有一种方法来捕获异常catch (...)以捕获绝对所有?
  3. 我不知道为什么std::rethrow_exception需要,我也不知道什么时候.

bam*_*s53 9

我不知道我称之为成语.如果用''"正确"'表示类似于std::vector默认情况下'正确'容器的使用方式,我认为没有一种特定的"正确"处理错误的方法.这是一种正确的方式,因为它是明确定义的行为.

2.首先,您必须print_backtrace()在不限于某些异常的上下文中调用,这意味着您必须在catch(...)块中调用它:

    try {
      run();
    } catch(...) {
      print_backtrace();
    }
Run Code Online (Sandbox Code Playgroud)

但是,您没有传递给函数的已知类型的例外.相反,您必须编写函数来以不同方式访问异常; 通过抛出该异常并在内部捕获它(因为这是您可以将已知类型的变量绑定到任意异常的唯一机制).

void print_backtrace(int depth = 0) {
  try {
    throw;
  }

  // this block shows how to handle exceptions of some known type
  // You can have your own types instead of std::exception
  catch (const std::exception & e) {
    std::cerr << std::string(depth, ' ') << e.what() << std::endl;
    try {
      std::rethrow_if_nested(e);
    }
    catch (...) {
      print_backtrace(++depth);
    }
  }

  // Not all nesting exceptions will be of a known type, but if they use the
  // mixin type std::nested_exception, then we can at least handle them enough to
  // get the nested exception:

  catch (const std::nested_exception & ne) {
    std::cerr << std::string(depth, ' ') << "Unknown nesting exception\n";

    try {
      ne.rethrow_nested();
    }
    catch (...) {
      print_backtrace(++depth);
    }
  }

  // Exception nesting works through inheritance, which means that if you
  // can't inherit from the type, then you can't 'mixin' std::nesting exception.
  // If you try something like std::throw_with_nested( int{10} ); Then you'll
  // hit this catch block when printing the backtrace.

  catch (...) {
    std::cerr << std::string(depth, ' ') << "Unknown exception\n";
  }
}
Run Code Online (Sandbox Code Playgroud)

3. std::rethrow_exception使用std::exception_ptr,这是一种可用于传输任意异常的类型.获得该异常的唯一方法是使用正常的异常处理机制来处理catch异常,这意味着您必须能够抛出该异常.这是什么rethrow_exception.这可以用于将任意异常从一个线程传输到另一个线程(如同std::future),或者将任意异常作为成员保存(如同std::nested_exception),或者将任意异常作为参数传递给将尝试打印的函数一些异常的描述.

void print_backtrace(std::exception_ptr e) {
  try {
    std::rethrow_exception(e);
  }

  catch (const std::exception & e) {
    // ...
Run Code Online (Sandbox Code Playgroud)