如何获取C++未处理异常的相关信息?是否可捕获所有线程的异常?
C++多线程未处理异常的捕获与信息获取方案
未处理异常的信息获取
首先可以确认:未处理的C++异常最终确实会调用std::terminate终止程序,在你自定义的terminate回调中,可以直接获取到未处理异常的相关信息,不需要额外的注册接口:
- 在C++11及更高版本的标准中,
std::current_exception()函数可以在terminate回调的执行上下文中,获取到当前未处理异常对应的std::exception_ptr实例,这个实例可以承载任意类型的异常信息。 - 拿到
std::exception_ptr后,你可以通过std::rethrow_exception重新抛出该异常,再通过catch分支匹配不同的异常类型,拿到对应信息:如果是继承自std::exception的异常,可以直接获取what()方法返回的异常描述;如果是自定义的非标准异常,可以补充对应的catch分支做特殊处理。
参考实现代码:
#include <exception> #include <iostream> #include <boost/stacktrace.hpp> void custom_terminate() { // 获取当前未处理的异常指针 std::exception_ptr unhandled_exc = std::current_exception(); if (unhandled_exc) { try { std::rethrow_exception(unhandled_exc); } catch (const std::exception& e) { std::cerr << "未处理标准异常,描述信息:" << e.what() << std::endl; } catch (...) { std::cerr << "未处理非标准异常,无法读取具体描述" << std::endl; } } // 打印栈回溯信息 std::cerr << "异常调用栈:\n" << boost::stacktrace::stacktrace() << std::endl; // 终止程序 std::abort(); } int main() { // 程序启动时注册自定义terminate回调 std::set_terminate(custom_terminate); // 后续业务代码 return 0; }
全局捕获所有线程异常的方案
C++标准中暂时没有你提到的std::set_default_exc_handler这类直接设置全局默认异常处理器的接口,但是可以通过线程入口封装的方式,实现所有线程的异常统一捕获,不需要逐个给数百个线程手动加try-catch:
- 实现一个通用的线程逻辑包装器,所有线程的业务逻辑在创建时都用该包装器包裹,包装器内部自带统一的异常处理逻辑,不管是
std::thread还是线程池的任务,都可以复用该包装器。
参考实现代码:
#include <functional> #include <thread> template <typename Func> auto thread_exception_wrapper(Func&& func) { return [task = std::forward<Func>(func)]() { try { return task(); } catch (...) { // 此处可添加统一异常处理逻辑:打日志、上报、保存异常信息等 std::cerr << "线程捕获到未处理异常" << std::endl; // 按需选择:可以直接终止程序,也可以吞掉异常让线程继续运行 std::terminate(); } }; } // 使用示例 void test_thread_logic() { throw std::runtime_error("线程异常测试"); } int main() { // 创建线程时用包装器包裹业务逻辑即可 std::thread test_thread(thread_exception_wrapper(test_thread_logic)); test_thread.join(); return 0; }
内容的提问来源于stack exchange,提问作者Arty
相关产品推荐
相关产品推荐

