POSIX兼容的平台上,SIGFPE是当一个进程执行了一个错误的算术操作时发送给它的信号。SIGFPE的符号常量头文件signal.h中定义。因为在不同平台上,信号数字可能变化,因此常使用信号名称。[1]

SIGFPE
描述错误的算术操作
默认动作进程异常终止
SA_SIGINFO宏
FPE_INTDIV 整数除以零
FPE_INTOVF 整数上溢
FPE_FLTDIV 浮点除以零
FPE_FLTOVF 浮点上溢
FPE_FLTUND 浮点下溢
FPE_FLTRES 浮点结果不准
FPE_FLTINV 无效浮点操作
FPE_FLTSUB 浮点下标越界

语源

SIG是信号名的通用前缀FPEfloating-point exception(浮点异常)的首字母缩略字。产生SIGFPE信号时并非一定要涉及浮点算术,之所以不修改名字是因为这么做会破坏向下兼容性

描述

导致SIGFPE被发送给进程的原因有很多。一个常见的例子是由于一个意外输入导致的溢出,或者在程序构造中的错误。

SIGFPE可以被处理。也就是说,程序员可以指定他们在接收到信号时想要的动作,例如调用一个子程序,忽略事件等。

在特定情形下,忽略SIGFPE可能导致程序出现意料之外的行为,包括但不限于由于不断重试违规操作而导致程序挂起。但是,忽略并非由计算造成的SIGFPE信号是安全的,例如通过kill系统调用发送的那些。

一个通常的疏忽是认为除以零是SIGFPE的唯一来源。在一些架构上(包括IA-32[来源请求]),使用INT_MIN(最小的可以被表示的负整数值)除以-1的整数除法也会触发这个信号,因为商是一个无法被表示的正数。(比如8位有符号整数可以表示-128、+127和它们之间的整数。-128÷-1=+128 > +127,因此无法被表示而产生溢出并触发此信号)

例子

这是一个尝试执行一个称为整数除以零,或FPE_INTDIV的错误算术运算的ANSI C程序的例子。

int main()
{
       int x = 42/0;
       return 0; /* Never reached */
}

在一个运行LinuxIA-32上编译运行,产生下列内容:

$ gcc -o sigfpe sigfpe.c
sigfpe.c: In function ‘main’:
sigfpe.c:3: warning: division by zero
$ ./sigfpe
Floating point exception (core dumped)

一个来自gdb栈跟踪显示在main函数中发生了SIGFPE信号:

Program received signal SIGFPE, Arithmetic exception.
0x08048373 in main ()

参考

参阅