信号SIGFPE问题

时间:2011-07-08 18:43:00

标签: c linux signals sigfpe

我是Linux信号的新手,请帮忙。 以下代码在Linux 2.6 gcc中运行时获得核心转储。

$ ./a.out
浮点异常(核心转储)

问题:
1.由于安装了过程信号掩码,第40行(z = x / y)生成的“SIGFPGE”不应被阻止吗?
2.如果没有阻塞,由于已经安装了信号处理程序,信号处理程序不应该捕获“SIGFPE”而不是核心转储? 3.如果我注释掉第40行(z = x / y),并使用第42行(加注(SIGFPE)),那么一切都按预期工作。这里x / 0和提升SIGFPE有什么区别?

以下是代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>

    void sig_handler(int signum)
    {
       printf("sig_handler() received signal %d\n", signum);
    }


    int main(int argc, char * argv[])
    {

       // setup signal mask, block all signals
       sigset_t set;
       sigfillset(&set);

       if(sigprocmask(SIG_BLOCK, &set, NULL)<0)
       {
          perror("failed to set sigmask");
          return -1;
       }

       // install signal handler for SIGFPE
       struct sigaction act;
       act.sa_handler = sig_handler;
       act.sa_mask = set;
       act.sa_flags = 0;
       if(sigaction( SIGFPE, &act, NULL)<0)
       {
          perror("sigaction failed");
          exit(-1);
       }

       volatile int x =1;
       volatile int y =0;
       volatile int z = x/y;

       //raise(SIGFPE);

       printf("point 1000\n");

       return 0;
    }

2 个答案:

答案 0 :(得分:4)

信号被阻塞时由硬件陷阱引起的任何SIGFPE都会导致未定义的行为:

  

如果在阻塞时生成任何SIGFPE,SIGILL,SIGSEGV或SIGBUS信号,则结果是未定义的,除非信号是由kill()函数,sigqueue()函数或raise(由)生成的( )功能。

(来自sigprocmask specification

答案 1 :(得分:0)

man signal

根据POSIX,在忽略非由kill(2)或raise(3)生成的SIGFPE,SIGILL或SIGSEGV信号后,进程的行为是不确定的。整数除以零会产生不确定的结果。

在某些体系结构上,它将生成SIGFPE信号。 (也将最大负整数除以-1可能会生成SIGFPE)。忽略此信号可能会导致无限循环。

我试图弄清楚为什么负/正无穷大是由零除而产生的:IEEE 754, division by zero

这是您永远不想得到的地方:

void divZeroHdlr(int sig) {
  printf("div by zero: %d\n",sig)
  exit(1);}

int main(int argc, char *argv[]) {
  signal(SIGFPE, divZeroHdlr)
  int n = 1/0}