为什么我不能忽略SIGSEGV信号? [英] Why can't I ignore SIGSEGV signal?

查看:183
本文介绍了为什么我不能忽略SIGSEGV信号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的code,

#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;
    }

当执行code,我得到分段错误。我忽略了使用SIG_IGN信号。所以,我不应该分割故障。对?然后,打印* P'值之后,的printf()语句必须执行过。对?

While executing the code, i'm getting segmentation fault. I ignored the signal using SIG_IGN. So I shouldn't get Segmentation fault. Right? Then, the printf() statement after printing '*p' value must executed too. Right?

推荐答案

您code是忽略SIGSEGV,而不是抓住它。回想一下,触发信号的指令处理信号后重新启动。你的情况,处理信号,以便下一次轮违规指令试过没有任何改变,它无法以同样的方式。

Your code is ignoring SIGSEGV instead of catching it. Recall that the instruction that triggered the signal is restarted after handling the signal. In your case, handling the signal didn't change anything so the next time round the offending instruction is tried, it fails the same way.

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

If you intend to catch the signal change this

signal(SIGSEGV, SIG_IGN);

这个

signal(SIGSEGV, sighandler);

您或许应该还可以使用的sigaction()而不是的信号()。请参阅相关的手册页。

You should probably also use sigaction() instead of signal(). See relevant man pages.

在您的情况下违规指令是试图取消引用NULL指针之一。

In your case the offending instruction is the one which tries to dereference the NULL pointer.

printf("%d", *p);

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

What follows is entirely dependent on your platform.

您可以使用 GDB 来确定哪些特定的汇编指令触发信号。如果你的平台是像我这样的话,你会发现指令

You can use gdb to establish what particular assembly instruction triggers the signal. If your platform is anything like mine, you'll find the instruction is

movl    (%rax), %esi

与RAX寄存器,保持0值,即 NULL 。一个(非移植!)方式的信号处理程序来解决这个问题是使用第三个参数信号的处理程序获取,即用户上下文。下面是一个例子:

with rax register holding value 0, i.e. NULL. One (non-portable!) way to fix this in your signal handler is to use the third argument signal your handler gets, i.e. the user context. Here is an example:

#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

它首先会导致通过尝试取消引用空地址执行的处理程序。然后,处理程序通过设置RAX变量的地址修复该问题ñ。一旦处理程序返回系统试违规的指令,这一次成功。 的printf()接收100作为其第二个参数。

It first causes the handler to be executed by attempting to dereference a NULL address. Then the handler fixes the issue by setting rax to the address of variable n. Once the handler returns the system retries the offending instruction and this time succeeds. printf() receives 100 as its second argument.

我强烈反对在你的程序中使用这样的非便携的解决方案,虽然。

I strongly recommend against using such non-portable solutions in your programs, though.

这篇关于为什么我不能忽略SIGSEGV信号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆