在POSIX/Linux下C语言能否通过SIGFPE的FPE_INTOVF捕获整数溢出异常
问题描述
我找遍了各处都没有查到相关信息,因此提出以下问题:
背景(多数开发者已知的内容):SIGFPE异常与si_code字段
在POSIX/Linux系统中存在名为SIGFPE的信号,尽管名称指向浮点异常,实际可用于上报浮点和整数算术错误。当我们使用sigaction()为SIGFPE注册信号处理函数时,处理函数可接收si_code字段说明SIGFPE的触发原因,其中一个可选值为FPE_INTDIV,可以通过整数除以0的操作快速测试该场景。
问题:FPE_INTOVF的可用性
我本次的疑问围绕si_code的特定值**FPE_INTOVF**展开,该值的描述为Value signalling integer overflow in case of SIGFPE signal。
但我从未见过该信号被触发的案例,也找不到让操作系统触发该信号的方法:我在C语言中制造整数溢出时,不会抛出任何SIGFPE异常。但SIGFPE存在FPE_INTOVF取值似乎暗示可以让系统在整数溢出时抛出该信号,就像整数除零的场景一样。
核心疑问
FPE_INTOVF是否是不可用的预留值?- 它是否只是尚未被任何POSIX兼容操作系统实现的信号占位符?
- 是否可以配置操作系统在整数溢出时抛出该信号?
我希望能通过sigaction()在C程序中捕获FPE_INTOVF信号。
补充说明
我清楚C语言中无符号整数溢出不属于错误,所有无符号整数运算都有回绕特性,但有符号整数溢出属于未定义行为,因此我认为FPE_INTOVF是用于处理有符号整数溢出场景的。
回答
核心结论
FPE_INTOVF既不是无意义的预留值,也不是完全未实现的占位符,主流POSIX系统(包括Linux)都支持识别该si_code,但默认不会自动触发,需要结合编译选项或手动编码才能生成该信号。
具体说明
- 实现状态
绝大多数POSIX兼容操作系统都已实现FPE_INTOVF的定义与识别逻辑:内核可以正常向用户进程传递带该si_code的SIGFPE信号,注册了sigaction的程序也可以正常读取该值,仅部分极简嵌入式系统可能未包含该定义。 - 默认不触发的原因
触发整数溢出异常依赖硬件与编译器的共同支持,而主流x86/ARM架构默认没有全局开关让所有整数运算自动触发溢出陷阱:- x86架构下仅
INTO(溢出中断)指令会在溢出标志位OF置1时触发异常,该异常会被内核转换为si_code=FPE_INTOVF的SIGFPE信号 - C语言标准将有符号整数溢出定义为未定义行为,编译器默认会利用该规则做性能优化,不会在普通算术运算后自动插入
INTO或其他溢出检查指令,因此默认不会触发该信号
- x86架构下仅
- 触发与捕获方法
你可以通过两种方式触发FPE_INTOVF,并通过sigaction正常捕获:- 手动编写汇编代码,在有符号整数运算后添加
INTO指令,溢出时就会自动触发对应信号 - 使用编译器的溢出检查编译选项:GCC/Clang都支持
-ftrapv选项,开启后编译器会在所有有符号整数运算后插入溢出检查逻辑,溢出时会触发SIGFPE且si_code为FPE_INTOVF;也可以配合未定义行为 sanitizer使用,通过环境变量配置让溢出场景抛出对应信号而非直接终止程序。
- 手动编写汇编代码,在有符号整数运算后添加
内容的提问来源于stack exchange,提问作者Luca Polito
相关产品推荐
相关产品推荐

