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

为何这段C++代码输出随机变化?移除terminate()后正常的原因

嗨,我来帮你把这个问题掰明白~

先把你的环境和代码整理清楚:

编译器信息

➜ ~ /usr/bin/c++ --version
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

测试代码

#include <iostream>
#include <exception>
#include <cstdlib>
void f() {
    try {
        throw std::runtime_error("Exception message.");
    } catch(std::runtime_error& e) {
        std::cout << e.what() << std::endl;
        throw;
    }
}
int main() {
    using namespace std;
    try {
        f();
    } catch(std::exception& e) {
        cout << e.what() << endl;
        terminate();
    }
    return EXIT_SUCCESS;
}

你的问题

移除main()的catch块里的terminate(),代码就能正常输出两次Exception message.;但保留terminate()时,会随机出现三种不同的输出组合,你搞不懂原因。


原因解释

1. 先理清楚代码的执行流程

当你保留terminate()时,代码的执行步骤是:

  • f()里抛出std::runtime_error,被自身的catch捕获,打印第一次Exception message.,然后通过throw;重新抛出这个异常
  • 重新抛出的异常被main()的catch捕获,打印第二次Exception message.
  • 调用terminate(),触发程序终止,此时libc++abi会向终端输出一条错误提示:libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Exception message.

2. 为什么输出顺序随机?

关键在这里:cout的输出是写到标准输出流(stdout),而libc++abi的错误提示是写到标准错误流(stderr)。这是两个完全独立的输出流,操作系统对它们的缓冲策略和输出调度是分开的——有时候stdout的内容先被刷到终端,有时候stderr的先出来,甚至可能穿插显示,这就导致了你看到的三种随机输出情况。

3. 为什么移除terminate()就正常了?

当你删掉terminate()后,main()的catch块执行完所有代码后,会继续走到return EXIT_SUCCESS;,程序正常退出:

  • 所有输出缓冲区(包括stdout)都会被自动刷新,所以两次Exception message.会按顺序打印
  • 因为异常已经被完全处理(没有未捕获的异常),libc++abi不会输出那条终止错误提示,所以程序的输出固定且符合预期

另外补充一点:terminate()是强制终止程序的函数,一旦调用,程序会立刻停止,不会执行后续的任何代码(比如你写的return EXIT_SUCCESS;根本不会被执行)。只有当你确定需要立刻终止程序,且不需要处理后续逻辑时,才适合调用它。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:25:03