C++未定义行为和异常处理
c++
#include <iostream>
int main() {
int* p = nullptr;
try {
std::cout << *p;
} catch (...) {
std::cout << "Caught an exception!";
}
return 0;
}
q1:代码会输出什么?
a:Linux上,通常会收到一个"段错误 (Segmentation fault)"的提示;
解析:未定义行为
根源:未定义行为 (Undefined Behavior, UB)
- 这里的
p
是一个空指针 (nullptr
) - 根据C++标准,解引用一个空指针是 未定义行为
- **未定义行为:**意味着C++标准没有规定此时程序必须做什么。编译器可以假定这种行为永远不会发生,并基于此进行优化。在运行时,任何事情都可能发生,包括但不限于:
- 程序立即崩溃
- 程序继续运行,但输出一个垃圾值
- 程序表现出完全不相关的奇怪行为
分析:
- 大多数现代操作系统(如Windows, Linux, macOS)上,内存地址
0
(空指针所指向的地址)受到操作系统的保护,任何用户程序都无权访问 - 当
*p
尝试读取该地址的数据时,CPU会触发一个硬件级别的保护错误。操作系统会捕获这个错误,并向该程序发送一个信号(如SIGSEGV
,即段错误信号),强制终止该程序的执行
try...catch
try...catch
块只能捕获通过 throw
关键字抛出的C++异常
- C++异常 :是一种程序内部的、由软件定义的控制流机制。当代码执行
throw std::runtime_error("错误信息");
时,一个std::runtime_error
类型的异常对象被创建并抛出,然后由匹配的catch
块来捕获和处理 - 段错误 (Segmentation Fault) :这不是一个C++异常。它是一个由操作系统发出的底层信号,通知进程其访问了非法内存。这个事件发生在C++运行时系统之外,因此C++的
try...catch
机制无法捕获它
How to understand:
try...catch
是程序内部处理"计划内意外"(如文件找不到、网络中断)的流程。- 而解引用空指针导致的崩溃,则像是房子地基塌了,属于结构性毁灭,内部的应急预案(
try...catch
)根本来不及反应