下面的小程序捕获一个浮点错误并打印出有关信号的信息。请注意,从 C 语言的角度来看,除以零是未定义的行为。例如,并非所有系统都有 POSIX 信号。因为编译器可以简单地预测错误,它甚至可能在 POSIX 系统上决定简单地删除所有代码,或者立即退出并出现错误。(我希望并假设 POSIX 系统上的编译器会生成一个执行预期操作的程序。在它下面会执行此操作。但这种希望以前已经失望了。)
#include <stdio.h>
#include <signal.h>
#include <stdlib.h> // for exit()
void fpehandler (int sig, siginfo_t *info, void *uc)
{
fprintf (stderr,
"Caught signal no. %d; code: %d (FPE_INTDIV would be %d)\n",
sig, info->si_code, FPE_INTDIV);
if(info->si_code == FPE_INTDIV)
{
fprintf (stderr,
"Yes, the error was an integer division by zero.\n");
}
// It's not officially safe to return from a handler
// of a "program error signal" (of which SIGFPE is an example).
// Plus many functions are not strictly safe to
// call in a signal handler (e.g. exit()).
// See https://www.securecoding.cert.org/confluence/display/c/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers .
// We call _Exit().
_Exit(0); // success, isn't it?
}
int main(void)
{
struct sigaction sa;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = fpehandler;
sigaction (SIGFPE, &sa, NULL);
// cause "floating point" error
printf("%d\n", 2/0);
// ---- below is unreachable code ;-) ----------
// We shouldn't be here. Something went wrong. return 1.
return 1;
}
当我在 cygwin、gcc 5.4.0 下运行它时,它会打印
$ gcc -Wall float-except.c -o float-except && ./float-except
float-except.c: In function 'main':
float-except.c:28:21: warning: division by zero [-Wdiv-by-zero]
printf("%d\n", 2/0);
^
Caught signal no. 8; code: 15 (FPE_INTDIV would be 15)
Yes, the error was an integer division by zero.