我遇到了在分段故障处理程序中引发分段故障的问题.尽管我已经解决了实际问题,但仍然令我感到困惑的是,为什么下面的程序没有进入无限循环:
#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)
在类似帖子的评论中:Segmentation fault within segmentation fault handler,一些人评论说它应该无限循环,但这不是当前行为.有人可以向我解释发生了什么吗?
解决方法:
您在信号处理程序中正在发出信号. POSIX standard says:
[table of safe functions]
All functions not in the above table are considered to be unsafe with respect to signals. In the presence of signals, all functions defined by this volume of IEEE Std 1003.1-2001 shall behave as defined when called from or interrupted by a signal-catching function, with a single exception: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined.
void C()是不安全的函数,因为它不在安全函数的列表中,因此让它引发信号会导致不确定的行为. (尽管措辞尚不清楚,但我认为这也意味着从信号处理程序函数引发信号也会导致UB).
作为未定义的行为,您不能依赖无限循环或任何其他此类行为.
其他要点:
>取消引用null是未定义的行为,并且不能保证首先生成SIGSEGV.
>在信号处理程序中调用printf是未定义的行为,因为这也不是表中的安全函数之一.
>从信号处理程序返回SIGSEGV也是UB.退出信号处理程序的唯一可移植方法是使用诸如exit之类的调用中止该过程.