c++中如何使用std::get_terminate获取结束处理函数_c++异常处理技巧【详解】

C++标准未提供std::get_terminate函数,仅定义了std::set_terminate;调用std::set_terminate返回前一个处理函数,这是唯一获取旧handler的方式。

你不能用 std::get_terminate 获取当前的终止处理函数 —— 这个函数根本不存在。C++ 标准库中没有 std::get_terminate,这是常见误解,源于把 std::set_terminate 和类似 C 的 get* 惯例混淆了。

为什么找不到 std::get_terminate?

C++ 标准只定义了 std::set_terminate,用于安装自定义终止处理函数;但**没有提供对应的获取接口**。标准明确要求实现“记住”当前的 terminate handler,但不暴露读取它的途径。

  • 调用 std::set_terminate 会返回上一个 handler(类型为 std::terminate_handler),这是唯一可间接“获取”的方式
  • 如果你没保存过返回值,就无法还原或检查当前 handler
  • 试图搜索或声明 std::get_terminate 会导致编译错误:error: 'get_terminate' is not a member of 'std'

如何安全地替换并保留原有 terminate handler?

典型做法是在调用 std::set_terminate 时捕获其返回值,即旧 handler。这既是“获取”的等效操作,也是恢复的唯一依据。

std::terminate_handler old_handler = std::set_terminate([]() {
    std::cerr << "Custom terminate called\n";
    // 注意:这里通常要手动 abort() 或 _Exit(),否则行为未定义
    std::abort();
});

// 后续想恢复?
std::set_terminate(old_handler);
  • 必须在自定义 handler 内显式调用 std::abort()_Exit()std::quick_exit(),否则程序行为未定义
  • old_handler 可能是 nullptr(如果之前从未设置过),调用前应判空
  • 该 handler 是全局状态,多线程下需注意设置时机(通常应在 main 开头或静态初始化阶段)

terminate handler 被触发的常见场景

它不是只在 throw 时起作用,而是在异常机制彻底失效时兜底:

  • 析构函数中抛出异常(且该异常未被栈展开过程捕获)
  • std::terminate() 被直接调用
  • 异常传播到 main() 之外(如线程函数退出时仍有未捕获异常)
  • 异常规范(C++17 已移除 throw(),但 noexcept 违反仍会调用 std::terminate

真正难处理的不是“怎么设”,而是 handler 内能安全做什么——此时栈已不可靠,newcout、锁、虚函数调用都可能崩溃。最稳妥的操作只有写入文件描述符(如 wri

te(2, ...))、调用 abort()_Exit()