




C++中除零不会抛出标准异常,整数除零是未定义行为,浮点除零按IEEE 754生成±inf/NaN;应主动检查除数而非依赖SIGFPE信号处理。
C++ 标准规定,整数除零是未定义行为(UB),throw 不会发生;浮点除零(如 1.0 / 0.0)按 IEEE 754 默认生成 ±inf 或 NaN,也不会触发 std::exception。所以用 try/catch 捕获 std::runtime_error 或通用异常完全无效。
SIGFPE 是操作系统发送的同步信号,仅对整数除零、溢出等特定算术错误触发(注意:glibc 下浮点除零默认不发 SIGFPE,需额外启用)。必须用 signal() 或更安全的 sigaction() 设置处理函数——不能靠 C++ 异常机制介入。
signal(SIGFPE, handler) 简单但有移植风险(如信号屏蔽、重入问题)sigaction() 更可靠,可精确控制 sa_mask 和 sa_flags(例如设 SA_RESTART 避免系统调用中断)std::cout、malloc、printf),只能用 write()、raise() 等不是所有整数除零都一定触发 SIGFPE,取决于编译器、优化级别和平台:
-O2 及以上可能直接优化掉“明显除零”,导致信号根本不会产生SIGFPE;ARM 等架构行为可能不同sigaction 忽略 SIGFPE(SA_HANDLER = SIG_IGN),则静默崩溃或 UBgdb 运行可捕获信号:handle SIGFPE stop print
示例最小可行信号处理:
#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::is_iec559 判断浮点是否支持 IEEE 754,再检查结果是否为 inf/nan
-ftrapv(有符号溢出)、-fsanitize=undefined(UBSan,含除零检测)信号只是兜底手段,容易漏、难调试、不可移植。把检查逻辑写进业务分支,比寄希望于 SIGFPE 处理器更可控。