回来的生活分割后违规 [英] Coming back to life after Segmentation Violation

查看:107
本文介绍了回来的生活分割后违规的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能恢复一个C程序的正常执行流程中,分段错误后?

 结构A {
    INT X;
};
A * A = 0;A-> X = 123; //这就是段违规发生//处理错误后,我想回到这里:
的printf(正常运行);
//我的源$ C ​​$ C其余....

我想类似的NullPointerException一种机制,是Java present,C#等。

注意:请不要告诉我,有C中的异常处理机制++,因为我知道,不要告诉我分配等之前,我应该检查每个指针

我真正想实现的是要回正常执行流程如上面的例子。我知道有些动作可以使用POSIX信号进行。它应该如何样子?其他的想法?


解决方案

 的#include<&unistd.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / mman.h>
#包括LT&;&signal.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&ucontext.h GT;无效safe_func(无效)
{
    看跌期权(安全吗?);
    出口(0); //不能回主,这是段错误发生在哪里。
}空虚
处理程序(INT原因,siginfo_t *信息,无效* UAP)
{
  //用于测试。永远不要调用标准输入输出功能于一身的信号处理程序,否则* /
  的printf(SIGSEGV上调地址%P \\ N信息 - > si_addr);
  ucontext_t *语境= UAP;
  / *在我的特定系统,用gcc -O2,违规指令编译
  生成的* F = 16;是6个字节。让我们尝试设置指令
  指针指向下一条指令(通用寄存器14 EIP,在Linux x86)* /
  上下文> uc_mcontext.gregs [14] + = 6;
  // alternativly,试图跳转到一个安全的地方
  //context->uc_mcontext.gregs[14] =(无符号整数)safe_func;
}INT
主(INT ARGC,CHAR *的argv [])
{
  结构sigaction的SA;
  sa.sa_sigaction =处理程序;
  为int * F = NULL;
  sigemptyset(安培; sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  如果(的sigaction(SIGSEGV,&安培; SA,0)){
      PERROR(sigaction的);
      出口(1);
  }
  //导致段错误
  * F = 16;
  看跌期权(还活着);
  返回0;
}$ ./a.out
SIGSEGV提出地址(无)
还活着

我会打的人用球棒,如果我看到了生产code这样的事情虽然,这是一个丑陋的,为乐趣的黑客。你不知道,如果段错误已经破坏了一些你的数据,你就必须恢复的任何理智的方式知道这一切现在好了,有这样做的没有可移植的方法。你唯一可以做的温和理智的事情就是尝试登录错误(使用write()方法直接,没有任何标准输入输出功能 - 他们不是信号安全的),也许重新启动程序。对于那些情况下,你已经开写superwisor过程监控子进程退出,记录它,并开始一个新的子进程好多了。

Is it possible to restore the normal execution flow of a C program, after the Segmentation Fault error?

struct A {
    int x;
};
A* a = 0;

a->x = 123; // this is where segmentation violation occurs

// after handling the error I want to get back here:
printf("normal execution");
// the rest of my source code....

I want a mechanism similar to NullPointerException that is present in Java, C# etc.

Note: Please, don't tell me that there is an exception handling mechanism in C++ because I know that, dont' tell me I should check every pointer before assignment etc.

What I really want to achieve is to get back to normal execution flow as in the example above. I know some actions can be undertaken using POSIX signals. How should it look like? Other ideas?

解决方案

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <signal.h>
#include <stdlib.h>
#include <ucontext.h>

void safe_func(void)
{
    puts("Safe now ?");
    exit(0); //can't return to main, it's where the segfault occured.
}

void
handler (int cause, siginfo_t * info, void *uap)
{
  //For test. Never ever call stdio functions in a signal handler otherwise*/
  printf ("SIGSEGV raised at address %p\n", info->si_addr);
  ucontext_t *context = uap;
  /*On my particular system, compiled with gcc -O2, the offending instruction
  generated for "*f = 16;" is 6 bytes. Lets try to set the instruction
  pointer to the next instruction (general register 14 is EIP, on linux x86) */
  context->uc_mcontext.gregs[14] += 6; 
  //alternativly, try to jump to a "safe place"
  //context->uc_mcontext.gregs[14] = (unsigned int)safe_func;
}

int
main (int argc, char *argv[])
{
  struct sigaction sa;
  sa.sa_sigaction = handler;
  int *f = NULL;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  if (sigaction (SIGSEGV, &sa, 0)) {
      perror ("sigaction");
      exit(1);
  }
  //cause a segfault
  *f = 16; 
  puts("Still Alive");
  return 0;
}

$ ./a.out
SIGSEGV raised at address (nil)
Still Alive

I would beat someone with a bat if I saw something like this in production code though, it's an ugly, for-fun hack. You'll have no idea if the segfault have corrupted some of your data, you'll have no sane way of recovering and know that everything is Ok now, there's no portable way of doing this. The only mildly sane thing you could do is try to log an error (use write() directly, not any of the stdio functions - they're not signal safe) and perhaps restart the program. For those cases you're much better off writing a superwisor process that monitors a child process exit, logs it and starts a new child process.

这篇关于回来的生活分割后违规的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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