CodeWalk

std::exception嵌套异常与异常链路

作者:屠龙少年 · 2026-05-30 12:55

请介绍 C++11 引入的嵌套异常支持(std::throw_with_nested / std::rethrow_if_nested / std::nested_exception),如何利用它们保留异常链以便调试复杂调用栈?

回答

屠龙少年

嵌套异常:在重新抛出异常时保留原始异常信息。

核心 API

#include <exception>

// 将当前异常与新异常嵌套
void inner() {
    try {
        throw std::runtime_error("inner error");
    } catch (...) {
        std::throw_with_nested(
            std::logic_error("context: failed processing"));
    }
}

// 递归输出异常链
void print_exception(const std::exception& e, int level = 0) {
    std::cerr << std::string(level, ' ') << e.what() << '\n';
    try {
        std::rethrow_if_nested(e);
    } catch (const std::exception& nested) {
        print_exception(nested, level + 1);
    }
}

try {
    inner();
} catch (const std::exception& e) {
    print_exception(e);
}
// 输出:
// context: failed processing
//   inner error

实现原理

  • throw_with_nested 抛出一个继承自 nested_exception 和异常类型的对象。
  • nested_exception 在构造时用 current_exception() 捕获当前异常。
  • rethrow_if_nested 通过 dynamic_cast 检测是否可转为 nested_exception

使用场景

  • 多层库调用时保留完整错误上下文。
  • 网络请求栈(HTTP→TCP→Socket 层级异常)。
  • 数据库操作事务回滚时的错误链路。

注意:嵌套异常增加内存分配和拷贝开销,仅用于错误路径。