C++中除零不会抛出标准异常,整数除零是未定义行为,浮点除零按IEEE 754生成±inf/NaN;应主动检查除数而非依赖SIGFPE信号处理。

除零在 C++ 中不会抛出标准异常
C++ 标准规定,整数除零是未定义行为(UB),throw 不会发生;浮点除零(如 1.0 / 0.0)按 IEEE 754 默认生成 ±inf 或 NaN,也不会触发 std::exception。所以用 try/catch 捕获 std::runtime_error 或通用异常完全无效。
SIGFPE 信号不是“异常”,需用 signal() 或 sigaction() 注册处理器
SIGFPE 是操作系统发送的同步信号,仅对整数除零、溢出等特定算术错误触发(注意:glibc 下浮点除零默认不发 SIGFPE,需额外启用)。必须用 signal() 或更安全的 sigaction() 设置处理函数——不能靠 C++ 异常机制介入。
-
signal(SIGFPE, handler)简单但有移植风险(如信号屏蔽、重入问题) -
sigaction()更可靠,可精确控制sa_mask和sa_flags(例如设SA_RESTART避免系统调用中断) - 处理函数中禁止调用非异步信号安全函数(如
std::cout、malloc、printf),只能用write()、raise()等
整数除零触发 SIGFPE 的实际条件很苛刻
不是所有整数除零都一定触发 SIGFPE,取决于编译器、优化级别和平台:
- Clang/GCC 在
-O2及以上可能直接优化掉“明显除零”,导致信号根本不会产生 - x86-64 上除零通常触发
SIGFPE;ARM 等架构行为可能不同 - 若程序已用
sigaction忽略SIGFPE(SA_HANDLER = SIG_IGN),则静默崩溃或 UB - 调试时用
gdb运行可捕获信号:handle SIGFPE stop print
示例最小可行信号处理:
立即学习“C++免费学习笔记(深入)”;
#include#include void fpe_handler(int sig) { write(2, "FPE caught!\n", 12); // async-signal-safe _exit(1); } int main() { signal(SIGFPE, fpe_handler); volatile int x = 0; return 5 / x; // volatile 阻止编译器优化掉 }
真正健壮的方案是主动检查,而非依赖信号
信号处理无法覆盖所有场景(比如优化后消失、多线程中不可靠、浮点默认不触发),且难以做恢复逻辑。生产代码应:
- 对除法操作前检查除数是否为零(尤其用户输入、配置值)
- 用
std::numeric_limits判断浮点是否支持 IEEE 754,再检查结果是否为::is_iec559 inf/nan - 需要严格算术检查时,启用编译器选项:
-ftrapv(有符号溢出)、-fsanitize=undefined(UBSan,含除零检测)
信号只是兜底手段,容易漏、难调试、不可移植。把检查逻辑写进业务分支,比寄希望于 SIGFPE 处理器更可控。










