繁体   English   中英

分段故障处理程序中的分段错误

[英]Segmentation fault in segmentation fault handler

我遇到了在分段错误处理程序中引发分段错误的问题。 虽然我已经修复了实际问题,但我仍然感到困惑,为什么以下程序不会进入无限循环:

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

void C() 
{
    int *p = NULL;
    *p = 3;
}

void B() 
{
    C();
}

void segfault_sigaction(int signal, siginfo_t *si, void *arg)
{
    printf("Came in sigaction.\n");
    //if(si)
        //printf("Caught segfault at address %p\n", si->si_addr);
    B();
}
int main(void)
{
    struct sigaction sa; 

    memset(&sa, 0, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = segfault_sigaction;
    sa.sa_flags   = SA_SIGINFO;

    sigaction(SIGSEGV, &sa, NULL);

    segfault_sigaction(0, NULL, NULL);

    return 0;
}

以上代码的输出如下:

Came in sigaction.
Came in sigaction.
Segmentation fault (core dumped)

在这篇类似文章的评论中: 分段错误处理程序中的分段错误一些人评论说它应该进入无限循环,但它不是当前的行为。 谁能向我解释发生了什么?

您在信号处理程序中发出信号。 POSIX标准说

[安全功能表]

上表中未包含的所有功能都被认为对信号不安全。 在存在信号的情况下,由IEEE Std 1003.1-2001卷定义的所有功能在信号捕获功能调用或中断时应按照定义运行,但有一个例外: 当信号中断不安全功能和信号时 - catch函数调用一个不安全的函数 ,行为是未定义的。

void C()是一个不安全的函数,因为它不在安全函数列表中,因此让它引发信号会导致未定义的行为。 (我认为它也意味着从信号处理函数中提升信号也会导致UB,尽管措辞不清楚)。

作为未定义的行为,您不能依赖于无限循环或任何其他此类行为。

其他要点:

  • 取消引用null是未定义的行为,并且不保证首先生成SIGSEGV。
  • 在信号处理程序中调用printf是未定义的行为,因为这也不是表中的安全函数之一。
  • SIGSEGV的信号处理程序返回也是UB。 退出信号处理程序的唯一可移植方法是使用诸如exit的调用中止该过程。

暂无
暂无

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

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