You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Boost异常中正确提取system_error的错误码?

解决boost::system::system_error无法直接捕获的问题

从你描述的异常类型和代码行为来看,核心问题是实际抛出的异常是被Boost异常机制包装后的类型,而非直接的boost::system::system_error或std::runtime_error。你看到的boost::exception_detail::clone_impl<boost::exception_detail::current_exception_std_exception_wrapper<std::runtime_error>>就是最直接的证据——原始的system_error被包装成了std::runtime_error的容器,再被clone_impl封装,导致直接捕获system_error的分支根本无法命中。

为什么会出现这种包装?

这通常是因为Boost组件内部使用了boost::throw_exception函数抛出异常,它会自动将原始异常包装成boost::exception的派生类(也就是你看到的clone_impl),目的是为了支持Boost的异常诊断信息扩展能力,比如添加额外的上下文信息。

解决方案:解开异常包装,捕获原始system_error

我们可以先捕获boost::exception,然后从包装结构中提取并重新抛出原始异常,这样就能正常命中system_error的捕获分支了。下面是修改后的代码:

try {
    this->service_.run();
} catch (const boost::system::system_error& e) {
    // 处理未被包装的直接抛出的system_error
    i_->playerLog->info("Exiting with system error. Error code: {} -- What: {}", 
                        e.code().value(), e.what());
} catch (const boost::exception& e) {
    // 尝试识别并解开特定的异常包装
    if (const auto* wrapped_ex = dynamic_cast<const boost::exception_detail::clone_impl<
            boost::exception_detail::current_exception_std_exception_wrapper<std::runtime_error>>*>(&e)) {
        try {
            // 重新抛出包装内保存的原始异常
            std::rethrow_exception(wrapped_ex->get_current_exception());
        } catch (const boost::system::system_error& se) {
            // 现在可以正常捕获到原始的system_error了
            i_->playerLog->info("Caught wrapped system error. Error code: {} -- What: {}", 
                                se.code().value(), se.what());
            return; // 处理完成后退出,避免执行后续的通用日志
        }
    }
    // 如果不是目标包装类型,输出通用Boost异常诊断信息
    i_->playerLog->info("Exiting with boost exception: {}", boost::diagnostic_information(e));
} catch (const std::exception& e) {
    // 兜底捕获其他未被处理的标准异常
    i_->playerLog->info("Exiting with standard exception: {}", e.what());
}

代码说明:

  1. 保留原有的system_error捕获分支,处理未被包装的直接抛出场景;
  2. 在boost::exception分支中,用dynamic_cast识别出你遇到的特定包装类型clone_impl<...>;
  3. 调用get_current_exception()获取包装内部保存的原始异常指针,再用std::rethrow_exception重新抛出;
  4. 在内部嵌套的try-catch中,就能正常捕获到原始的system_error,提取错误码和异常信息;
  5. 最后添加兜底的std::exception捕获,确保所有异常都能被妥善处理。

更通用的替代写法

如果你不想硬编码具体的包装类型名称,也可以借助Boost异常的错误信息提取能力,尝试获取原始异常指针:

catch (const boost::exception& e) {
    if (const auto* ex_ptr = boost::get_error_info<boost::exception_detail::current_exception>(e)) {
        try {
            std::rethrow_exception(*ex_ptr);
        } catch (const boost::system::system_error& se) {
            i_->playerLog->info("Unwrapped system error: {} - {}", se.code().value(), se.what());
        }
    }
    // 输出通用诊断信息
    i_->playerLog->info("Boost exception details: {}", boost::diagnostic_information(e));
}

这种写法更灵活,不需要依赖具体的包装类型名称,但需要确保你的Boost版本支持boost::exception_detail::current_exception这个错误信息类型。

内容的提问来源于stack exchange,提问作者Germán Diago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:43:23