【问题标题】:Segmentation fault in segmentation fault handler分段错误处理程序中的分段错误
【发布时间】:2018-11-18 01:06:18
【问题描述】:

我遇到了在分段错误处理程序中引发分段错误的问题。虽然我已经解决了实际问题,但我仍然很困惑为什么下面的程序没有进入无限循环:

#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)

在这个类似帖子的 cmets 中:Segmentation fault within segmentation fault handler 一些人评论说它应该进入无限循环,但这不是当前的行为。有人可以向我解释发生了什么吗??

【问题讨论】:

标签: c linux debugging linux-kernel operating-system


【解决方案1】:

您在信号处理程序中发出信号。 POSIX standard says:

[安全函数表]

上表中没有的所有函数都被认为对信号不安全。在存在信号的情况下,本卷 IEEE Std 1003.1-2001 定义的所有函数在从信号捕获函数调用或被信号捕获函数中断时的行为应与定义相同,但有一个例外:当信号中断不安全函数并且信号捕捉函数调用不安全函数,行为未定义。

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

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

其他要点:

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

【讨论】:

  • 为什么'void C()'是不安全的?是每个用户定义的函数都默认进入不安全列表,还是这个函数的声明/定义有问题?
  • 除安全列表中的函数外,所有函数都是不安全的
  • 但我没有得到任何未定义的行为。正如马克在 cmets 中指出的那样,我让我的程序无限工作,直到堆栈溢出。
  • @Pushpendra 您误解了“未定义行为”的含义。不能说你没有得到任何东西。
  • 好吧,你的意思是即使我们得到了想要的输出,例如它的行为可能是未定义的。
猜你喜欢
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
相关资源
最近更新 更多