为什么我在下面的C代码中得到连续的SIGSEGV

为什么我在下面的C代码中得到连续的SIGSEGV,c,linux,signals,C,Linux,Signals,我正在努力学习信号。我知道无效的内存访问将导致SEG故障。所以,我为SIGSEGV信号注册了一个信号处理器 #include <stdio.h> #include <signal.h> void sighandler(int signum) { printf("%s\n", __func__); } int main() { int *a = NULL; signal(SIGSEGV, sighandler); *a = 5;

我正在努力学习信号。我知道无效的内存访问将导致SEG故障。所以,我为SIGSEGV信号注册了一个信号处理器

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


void sighandler(int signum)
{
    printf("%s\n", __func__);
}

int main()
{
    int *a = NULL;
    signal(SIGSEGV, sighandler);
    *a = 5;
    return 0;
}
#包括
#包括
无效信号器(内部信号)
{
printf(“%s\n”,函数);
}
int main()
{
int*a=NULL;
信号(SIGSEGV、sighandler);
*a=5;
返回0;
}

运行这段代码,我不断地得到SIGSEGV信号。我想我应该只收到一次信号。你们能解释一下为什么在SEGV处理程序完成后,我会不断收到信号,触发的指令会重新执行。由于您没有采取任何措施防止下一次执行出错,因此您再次获得SEGV,无限期


详见。

信号处理程序返回到触发它的指令,即导致它循环的
*a=5

您有几个问题,包括在信号处理程序中使用
printf

有安全和不安全的处理方法

笔记 一般情况下,不建议对信号处理使用
信号(2)

由于信号语义的工作方式,SIGSEGV的处理更加复杂。从手册页引用:

signal()的唯一可移植用途是将信号的配置设置为SIG_DFL或SIG_IGN。使用signal()时的语义 要建立一个信号处理程序,请在 系统(和POSIX.1明确允许这种变化);请勿将其用于此目的

POSIX.1通过指定sigaction(2)解决了可移植性混乱问题,sigaction(2)在 调用信号处理器;使用该接口而不是signal()

因此,您应该做的第一件事是使用
sigaction

接下来,处理SIGSEGV是一个奇怪的怪兽:

有好的答案,并进入具体的细节。在这里给出的一些答案中有外部链接

如何使用信号(2)执行此操作 好吧:-)假设你想使用信号(2),你想用一种奇怪的方式来处理这个问题

您可以使用
sigjmpset
siglongjmp

sigjmpset
标记了
siglongjmp
应该跳转到的点。第一次调用
sigjmpset
时(设置点),它返回0。当
siglongjmp
跳转到它时(这意味着跳远的结果会再次调用它),它返回1

这意味着我们可以做到:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>

sigjmp_buf env;
int sigsav;

void sighandler(int signum)
{

    const char msg[] = "Skipping signal\n";
    write(2, msg, sizeof(msg));
    siglongjmp(env, sigsav);
}

int main()
{
    int *a = NULL;

    signal(SIGSEGV, sighandler);
    if(!sigsetjmp(env, sigsav)) {
        printf("setting value of a\n");
    *a = 5;
    }
    else {
    printf("returned to sigsetjmp, but now we skip it!\n");
    }
    return 0;
}
#包括
#包括
#包括
#包括
sigjmp_buf env;
int-sigsav;
无效信号器(内部信号)
{
const char msg[]=“跳过信号\n”;
写(2,msg,sizeof(msg));
siglongjmp(env,sigsav);
}
int main()
{
int*a=NULL;
信号(SIGSEGV、sighandler);
如果(!sigsetjmp(env,sigsav)){
printf(“a的设置值”);
*a=5;
}
否则{
printf(“返回到sigsetjmp,但现在我们跳过它!\n”);
}
返回0;
}

虽然你的观点是正确的,但这更多的是一个评论而不是一个答案:-)另请参见,朋友们。必须在信号处理程序中使用异步安全函数。