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

异常处理技术疑问:catch块是否仅执行?多catch块遇二次异常如何捕获?

关于C++ Catch块的两个常见问题解答

嘿,咱们逐个来理清这两个问题:

1. Catch块是否仅会在异常发生时执行?

没错,catch块只有当它对应的try块抛出了与自身异常类型匹配的异常,且这个异常没有被更内层的catch捕获时,才会被执行。如果try块里没有抛出任何异常,或者抛出的异常类型和当前catch块的签名不匹配,那这个catch块就会直接被跳过,完全不会执行。

举个简单的例子就能明白:

#include <iostream>
#include <stdexcept>

int main() {
    try {
        std::cout << "我在try块里,没抛异常~" << std::endl;
    } catch (const std::runtime_error& e) {
        // 这个catch块根本不会运行,因为try里没抛匹配的异常
        std::cerr << "捕获到异常:" << e.what() << std::endl;
    }

    try {
        throw std::logic_error("抛出一个逻辑异常");
    } catch (const std::runtime_error& e) {
        // 类型不匹配,这个catch也不会执行
        std::cerr << "捕获到运行时异常:" << e.what() << std::endl;
    } catch (const std::exception& e) {
        // 这个catch会执行,因为logic_error继承自exception,类型匹配
        std::cerr << "捕获到异常:" << e.what() << std::endl;
    }
    return 0;
}

2. 栈展开过程中抛出第二个异常,catch块会捕获哪些?

这个情况要特别注意:当第一个异常抛出后,程序会进入栈展开阶段——也就是沿着调用栈往上走,依次销毁当前栈帧里的局部对象,同时寻找能匹配第一个异常的catch块。如果在这个栈展开的过程中(比如某个局部对象的析构函数里抛出了第二个异常),而第一个异常还没被任何catch块处理,那根据C++标准,程序会直接调用std::terminate()终止运行,不会有任何catch块去捕获第二个异常,第一个异常也得不到处理。

看这个反面例子:

#include <iostream>
#include <stdexcept>

class TroubleMaker {
public:
    ~TroubleMaker() {
        // 栈展开时析构这个对象,抛出第二个异常
        throw std::runtime_error("析构函数里的异常");
    }
};

void innerFunc() {
    TroubleMaker obj;
    // 抛出第一个异常
    throw std::logic_error("第一个异常");
}

int main() {
    try {
        innerFunc();
    } catch (const std::exception& e) {
        // 这个catch块永远不会被执行!
        std::cerr << "捕获到异常:" << e.what() << std::endl;
    }
    return 0;
}

运行这段代码,你会发现程序直接崩溃,不会进入任何catch块——因为栈展开时析构函数抛出的第二个异常,触发了std::terminate()。

不过有个例外:如果第一个异常已经被某个catch块成功捕获了,之后在处理这个异常的过程中(比如catch块内部)又抛出第二个异常,那第二个异常可以被外层的try-catch结构捕获(如果有的话),但这已经不属于栈展开阶段的情况了。


内容的提问来源于stack exchange,提问作者Allanqunzi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:18:10