std::exception嵌套异常与异常链路
请介绍 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 层级异常)。
- 数据库操作事务回滚时的错误链路。
注意:嵌套异常增加内存分配和拷贝开销,仅用于错误路径。