为何这段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
相关产品推荐
相关产品推荐

