如何处理C++中未处理的异常?

来源:前端技术作者:阿里山老登头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何处理C++中未处理的异常?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何处理C++中未处理的异常?》有用,将其分享出去将是对创作者最好的鼓励。

在C++程序运行过程中,当抛出的异常没有被任何catch块捕获时,就会产生未处理的异常,此时程序会触发默认的终止逻辑,大部分情况下会直接崩溃退出。这种情况在复杂的多模块程序中很容易出现,需要开发者提前做好应对方案。

未处理异常的默认处理机制

C++标准规定,当未处理的异常产生时,运行时会自动调用std::terminate函数。而std::terminate的默认行为是调用std::abort函数,直接终止程序,不会执行后续的栈展开和析构逻辑,可能会导致资源泄漏等问题。

以下是一段会产生未处理异常的示例代码:

#include <iostream>
#include <stdexcept>

// 抛出运行时异常的函数
void throw_error() {
    throw std::runtime_error("测试未处理的异常");
}

int main() {
    // 这里没有捕获throw_error抛出的异常
    throw_error();
    std::cout << "这行代码不会被执行" << std::endl;
    return 0;
}

运行上述代码时,程序会在抛出异常后直接终止,不会输出后面的内容。

自定义未处理异常的处理函数

C++提供了std::set_terminate函数,允许开发者自定义std::terminate被调用时的处理逻辑,替代默认的std::abort行为。自定义的处理函数需要满足无返回值、无参数的要求。

我们可以通过以下步骤实现自定义处理:

  • 定义符合要求的终止处理函数,可以在函数中记录异常信息、释放必要资源等
  • 调用std::set_terminate将自定义的终止处理函数注册到运行时
  • 如果需要在处理函数中获取异常信息,可以结合std::current_exceptionstd::rethrow_exception来捕获当前未处理的异常

以下是自定义未处理异常处理的示例代码:

#include <iostream>
#include <exception>
#include <stdexcept>
#include <typeinfo>

// 自定义的终止处理函数
void custom_terminate_handler() {
    std::cout << "捕获到未处理的异常,开始执行自定义处理逻辑" << std::endl;
    // 尝试获取当前的异常
    if (std::current_exception()) {
        try {
            // 重新抛出异常以便捕获
            std::rethrow_exception(std::current_exception());
        } catch (const std::exception& e) {
            std::cout << "异常类型: " << typeid(e).name() << std::endl;
            std::cout << "异常信息: " << e.what() << std::endl;
        } catch (...) {
            std::cout << "捕获到未知类型的异常" << std::endl;
        }
    } else {
        std::cout << "没有可获取的异常信息" << std::endl;
    }
    // 处理完成后可以选择正常退出或者执行其他逻辑
    std::cout << "自定义处理完成,程序退出" << std::endl;
    exit(1);
}

// 抛出异常的测试函数
void test_func() {
    throw std::runtime_error("这是自定义的运行时异常");
}

int main() {
    // 注册自定义的终止处理函数
    std::set_terminate(custom_terminate_handler);
    // 调用会抛出异常但没有捕获的函数
    test_func();
    std::cout << "这行代码不会被执行" << std::endl;
    return 0;
}

运行上述代码后,程序不会直接崩溃,而是会先执行custom_terminate_handler函数中的逻辑,输出异常相关信息后再退出。

处理未处理异常的最佳实践

虽然可以通过自定义std::terminate处理函数来应对未处理的异常,但最好的方式还是从根源上减少未处理异常的出现:

  • 在程序的入口函数(如main函数)中添加顶层的catch块,捕获所有可能的异常,避免异常向上传递到运行时
  • 对于可能抛出异常的函数,明确标注异常规格(如果使用noexcept,要确保函数内部不会抛出异常,否则会直接调用terminate)
  • 在多线程程序中,每个线程的入口函数都要做好异常捕获,因为线程内未处理的异常会直接终止整个程序
  • 自定义终止处理函数只适合做最后的兜底处理,比如记录崩溃日志、保存关键数据等,不要在其中做复杂的业务逻辑

不同场景下的注意事项

在以下场景中处理未处理异常需要额外注意:

析构函数中抛出异常

如果析构函数抛出了异常且没有在析构函数内部捕获,而此时又正在栈展开过程中(比如之前已经有异常抛出),程序会直接调用std::terminate,因此析构函数应该尽量保证不抛出异常,或者将异常在析构函数内部处理完毕。

noexcept函数中的异常

标记为noexcept的函数如果抛出了异常,不管是否被捕获,都会直接触发std::terminate,因此在给函数添加noexcept修饰时要确认函数内部不会抛出任何异常。

未处理的异常处理是C++程序稳定性保障的重要一环,开发者需要结合自定义终止处理和顶层异常捕获两种方式,最大程度减少程序异常崩溃的概率。

C++未处理异常异常处理terminate函数set_terminate修改时间:2026-06-13 10:33:58

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。