繁体   English   中英

信号处理(SIGFPE)

[英]Signal handling(SIGFPE)

在以下代码中:

#include <unistd.h>
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
using namespace std;
void signal_callback_handler(int signum)

{
printf ("Caught signal %d\n", signum);
exit (signum);
}

int main()
{
signal (SIGFPE, signal_callback_handler);

int a=4;
int b=55444;

while (1)
{
printf ("Program processing stuff here.\n");
cout<<b/a;
a--;
b++;
sleep (1);
}
return EXIT_SUCCESS;
}

当变量'a'变为0时,程序从OS获得SIGFPE信号,程序终止并显示消息:“捕获信号8”。 但是,如果我发表评论,“退出(signum);” 在'signal_callback_handler'定义中,程序继续无休止地运行并继续在屏幕上打印“Caught Signal 8”语句。 为什么会这样? 为什么这个信号会以某种方式反复生成?

我期待信号将被生成一次,并且在经过信号处理函数之后,程序将在'cout << b / a'语句之后恢复,然后程序将继续正常。但是,因为这没有发生,我怎样才能实现目标?

我认为gcc会从信号处理程序为你创建一个返回点到while循环,它会不断跳入和跳出信号处理程序。 您可以尝试使用gcc的no_return属性来确保您的程序不会返回到while循环,并且您可以通过调用其他函数来继续您的程序。

建议像SIGILL或SIGFPE这样的信号停止执行而不尝试恢复。

POSIX说:

在正常从信号捕获函数返回不是由kill(),sigqueue()或raise()生成的SIGBUS,SIGFPE,SIGILL或SIGSEGV信号之后,进程的行为是未定义的。

在许多实现中,当处理程序完成重新生成生成异常的指令时,生成新的SIGFPE等。

在x86中,这是因为除法错误是一个错误 ,这意味着当控制流返回时,程序计数器( %rip )将指向先前错误代码的地址, 而不是下一条指令。

处理SIGFPE的常规策略是使用setjmp从信号处理程序跳转到可恢复状态。

一个简单的例子来自你自己的代码(顺便说一下,永远不要在信号处理程序中使用printf() ):

#include <setjmp.h>
using namespace std;

jmp_buf excep;

void signal_callback_handler(int signum)

{
longjmp(excep, 1);
}

int main()
{
signal (SIGFPE, signal_callback_handler);

int a=4;
int b=55444;

    while (1)
    {
        printf ("Program processing stuff here.\n");
        if ( setjmp(excep) == 0 ) {
            // normal control flow
            cout<<b/a;
        }
        else {
            // from longjmp
            printf("Exception caught\n");
        }
        a--;
        b++;
        sleep (1);
    }
return EXIT_SUCCESS;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM