c - 为什么我不能忽略 SIGSEGV 信号?

标签 c unix signals

这是我的代码,

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

int main(int argc,char ** argv)
   {
     char *p=NULL;
     signal(SIGSEGV,SIG_IGN); //Ignoring the Signal
     printf("%d",*p);
     printf("Stack Overflow"); //This has to be printed. Right?
   return 0;
    }

在执行代码时,出现段错误。我使用 SIG_IGN 忽略了信号。所以我不应该得到段错误。正确的?然后,打印'*p' 值后的printf() 语句也必须执行。正确的?

最佳答案

您的代码忽略了 SIGSEGV 而不是捕获它。回想一下,触发信号的指令在处理信号后重新启动。在你的例子中,处理信号并没有改变任何东西,所以下一次尝试有问题​​的指令时,它会以同样的方式失败。

如果你打算捕捉信号改变这个

signal(SIGSEGV, SIG_IGN);

对此

signal(SIGSEGV, sighandler);

您可能还应该使用 sigaction() 而不是 signal()。请参阅相关手册页。

在您的情况下,有问题的指令是试图取消引用 NULL 指针的指令。

printf("%d", *p);

以下内容完全取决于您的平台。

您可以使用gdb 来确定触发信号的特定汇编指令。如果你的平台和我的一样,你会发现指令是

movl    (%rax), %esi

rax 寄存器保持值 0,即 NULL。在信号处理程序中解决此问题的一种(不可移植!)方法是使用处理程序获取的第三个参数信号,即用户上下文。这是一个例子:

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

#define __USE_GNU
#include <ucontext.h>

int *p = NULL;
int n = 100;

void sighandler(int signo, siginfo_t *si, ucontext_t* context)
{
  printf("Handler executed for signal %d\n", signo);
  context->uc_mcontext.gregs[REG_RAX] = &n;
}

int main(int argc,char ** argv)
{
  signal(SIGSEGV, sighandler);
  printf("%d\n", *p); // ... movl (%rax), %esi ...
  return 0;
}

这个程序显示:

Handler executed for signal 11
100

它首先通过尝试解除对 NULL 地址的引用来执行处理程序。然后处理程序通过将 rax 设置为变量 n 的地址来解决问题。一旦处理程序返回,系统就会重试有问题的指令,这次成功了。 printf() 接收 100 作为其第二个参数。

不过,我强烈建议不要在您的程序中使用此类不可移植的解决方案。

关于c - 为什么我不能忽略 SIGSEGV 信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8456085/

相关文章:

c - 什么时候进行代码优化?

unix - Amazon IAM 可以用作主机的身份验证方法吗?

linux - SVN 导出命令成功运行但文件未出现在目标路径中

Python signal.signal 是否阻止传播?

linux - 在 x86 上发送用户模式中断

c - 为什么我的 C 程序在使用 for 循环时只产生零答案?

c - Udp readfrom直到结束

c - 免费提供错误

c - 是否可以终止不响应信号的程序?

c - SIGPOLL(SIGIO)问题: interrupt while executing a handler